diff --git a/src/erc7730/common/abi.py b/src/erc7730/common/abi.py index 919b256..fe5fdc4 100644 --- a/src/erc7730/common/abi.py +++ b/src/erc7730/common/abi.py @@ -22,7 +22,7 @@ named_param: type identifier? named_tuple: tuple array* identifier? - array: "[]" + array: "[]" | "[" /[0-9]+/ "]" identifier: /[a-zA-Z$_][a-zA-Z0-9$_]*/ type: identifier array* @@ -61,8 +61,8 @@ def named_tuple(self, ast: Any) -> Component: # Separate arrays from name # Arrays are "[]", name is anything else - arrays = [elem for elem in ast[1:] if elem == "[]"] - names = [elem for elem in ast[1:] if elem != "[]"] + arrays = [elem for elem in ast[1:] if isinstance(elem, str) and elem.startswith("[")] + names = [elem for elem in ast[1:] if not (isinstance(elem, str) and elem.startswith("["))] # Build type with array suffixes type_str = "tuple" + "".join(arrays) @@ -73,6 +73,8 @@ def named_tuple(self, ast: Any) -> Component: return Component(name=name, type=type_str, components=components) def array(self, ast: Any) -> str: + if ast: + return f"[{ast[0]}]" return "[]" def identifier(self, ast: Any) -> str: diff --git a/tests/common/test_abi.py b/tests/common/test_abi.py index f74ff06..26dde7b 100644 --- a/tests/common/test_abi.py +++ b/tests/common/test_abi.py @@ -67,6 +67,31 @@ "mixed(bytes32[][] data, (address a,uint256 b)[][] _tuples, string name)", "mixed(bytes32[][],(address,uint256)[][],string)", ), + # fixed-size arrays + ( + "exchange(address[11] _route, uint256[5][5] _swap_params, uint256 _amount, uint256 _min_dy)", + "exchange(address[11],uint256[5][5],uint256,uint256)", + ), + # fixed-size array single dimension + ( + "foo(uint256[3] values)", + "foo(uint256[3])", + ), + # mixed fixed and dynamic arrays + ( + "bar(address[5] addrs, uint256[] amounts, bytes32[2][] pairs)", + "bar(address[5],uint256[],bytes32[2][])", + ), + # fixed-size array of tuples + ( + "baz((uint256,address)[3] items)", + "baz((uint256,address)[3])", + ), + # higher-dimensional fixed-size arrays + ( + "multi(uint256[2][3][4] cube)", + "multi(uint256[2][3][4])", + ), ], ) def test_reduce_signature(signature: str, expected: str) -> None: