fix(abi): encode zero-width static aggregates as empty bytes#4777
Open
spokodev wants to merge 1 commit into
Open
fix(abi): encode zero-width static aggregates as empty bytes#4777spokodev wants to merge 1 commit into
spokodev wants to merge 1 commit into
Conversation
An empty fixed array (`T[0]`) or empty tuple (`()`) is a zero-width
static type. `encodeArray`/`encodeTuple` built the static encoding via
`concat(preparedParams.map(p => p.encoded))` over an empty array, but
`concat([])` routes to `concatBytes([])` (because `values[0]` is
`undefined`, not a string) and returns an empty `Uint8Array` instead of
the hex string `'0x'`. That `Uint8Array` then poisons the string-vs-bytes
detection in `encodeParams`, producing wrong bytes or an uncaught
`TypeError: x.replace is not a function`.
Per the ABI spec, `enc(T[0])` and `enc(())` are zero-length, so emit
`'0x'` directly when there are no prepared params.
encodeAbiParameters([{type:'uint256[0]'},{type:'uint256'}], [[], 3n])
// before: Uint8Array(66) after: 0x..0003 (32 bytes)
encodeAbiParameters([{type:'uint256'},{type:'tuple',components:[]}], [5n, []])
// before: throws after: 0x..0005 (32 bytes)
ethers `AbiCoder.encode` returns the 32-byte uint256 for both inputs.
|
|
@spokodev is attempting to deploy a commit to the Wevm Team on Vercel. A member of the Team first needs to authorize it. |
Author
|
Sibling PR for a separate root cause: #4778 (fromRlp trailing bytes). |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
An empty fixed array (
T[0]) or empty tuple (()) is a zero-width static type. InencodeAbiParameters.ts, the static branches ofencodeArrayandencodeTuplebuild their encoding withconcat(preparedParams.map(p => p.encoded))over an empty array.concat([])(inutils/data/concat.ts) checkstypeof values[0] === 'string'. For an empty inputvalues[0]isundefined, so it routes toconcatBytes([])and returns an emptyUint8Arrayrather than the hex string'0x'. ThatUint8Arraythen leaks back intoencodeParams, poisoning the string-vs-bytes detection and producing either wrong bytes or an uncaughtTypeError.The function's documented return type is
Hex, neverUint8Array.Reproduction
Oracle
Per the ABI spec,
enc(T[0])andenc(())are zero-length: an empty fixed array or empty tuple contributes no bytes. ethers agrees:Fix
Emit
'0x'directly whenpreparedParamsis empty in the static branch ofencodeArrayandencodeTuple, instead of relying onconcat([]). The change is local to the two aggregate encoders;concat's behaviour is untouched (it has other callers).Added tests cover both repros against the ethers/ABI-spec oracle.
This is a separate root cause from #921 (empty dynamic
bytes[]) and from the RLP trailing-bytes fix in a sibling PR.