Skip to content

fix: match array args with a zero digit in the element size in AbiItem.fromAbi - #523

Open
Revinand wants to merge 2 commits into
wevm:mainfrom
Revinand:fix/abiitem-array-regex
Open

Revinand wants to merge 2 commits into
wevm:mainfrom
Revinand:fix/abiitem-array-regex

Conversation

@Revinand

@Revinand Revinand commented Oct 22, 2026 •

Copy link
Copy Markdown

AbiItem.fromAbi picks an overload with isArgOfType and checks it with getAmbiguousTypes. Several array and tuple arguments resolved to the wrong overload, so AbiFunction.encodeData encoded against the wrong function or threw:

const abi = Abi.from(['function foo(bool x)', 'function foo(uint160[] x)'])

AbiItem.fromAbi(abi, 'foo', { args: [[1n, 2n]] })
// before: foo(bool)
// after:  foo(uint160[])

AbiFunction.encodeData(AbiFunction.fromAbi(abi, 'foo'), [[1n, 2n]])
// before: throws Invalid boolean value: "1,2"
// after:  0x7bde9aac...
  • Array types were matched with /[a-z]+[1-9]{0,3}(\[[0-9]{0,}\])+$/. Its [1-9] class rejects any element size with a 0 in it, so uint160[], bytes20[], int40[2] and uint120[][] never matched, and fromAbi fell back to the first overload, as above.
  • Fixed-length arrays matched any length. With foo(uint256[3]) and foo(uint256[2]), [1n, 2n, 3n] resolved to foo(uint256[2]) and encoding threw ArrayLengthMismatchError.
  • Tuple object args were read by position with Object.values. With foo((address a, string b)) and foo((string a, address b)), { b: 'hello', a: <address> } resolved to the second one and encoding threw InvalidAddressError.
  • getAmbiguousTypes returned at the first pair of tuple parameters, so foo((uint256), address) / foo((uint256), bytes20) resolved to the last one instead of throwing. It also threw a TypeError when the two tuples had a different number of components, e.g. foo((uint256[] a)) and foo((uint256[] a, uint256 b)) with { a: [1n], b: 2n }.

Arrays are now matched with the existing getArrayComponents helper from internal/abiParameters, which also gives the length to check. Tuple object values are read by component name, as AbiParameters.encode does. The element type is still checked by the recursive isArgOfType call, so an invalid size such as uint69[] is still rejected, as the existing test expects.

Now that bytes20[] can match, getAmbiguousTypes also compares the element types of two array parameters, using the first item. An address[] / bytes20[] overload pair then throws AbiItem.AmbiguityError, like address / bytes20, instead of picking the last item. An empty array matches both element types, so address[] against string[] or bytes[] is ambiguous too when the array is empty.

These are the same changes as wevm/viem#5281, which merged this fix in viem.

Added isArgOfType rows for uint160[], int40[2], uint120[][], bytes20[] and a too-long uint256[2], overload tests for the zero digit, fixed-length and tuple object cases, ambiguity tests for array, empty array and tuple overloads, and getAmbiguousTypes cases for arrays. They fail without the change.

@vercel

vercel Bot commented Oct 22, 2026

Copy link
Copy Markdown

@Revinand is attempting to deploy a commit to the Wevm Team on Vercel.

A member of the Team first needs to authorize it.

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant