diff --git a/accounts/abi/selector_parser.go b/accounts/abi/selector_parser.go index 75609b28a6cc..e0cf634ba2b9 100644 --- a/accounts/abi/selector_parser.go +++ b/accounts/abi/selector_parser.go @@ -86,6 +86,9 @@ func parseCompositeType(unescapedSelector string) ([]interface{}, string, error) if len(rest) == 0 || rest[0] != ')' { return nil, "", fmt.Errorf("expected ')', got '%s'", rest) } + if len(rest) >= 3 && rest[1] == '[' && rest[2] == ']' { + return append(result, "[]"), rest[3:], nil + } return result, rest[1:], nil } @@ -112,7 +115,12 @@ func assembleArgs(args []interface{}) ([]ArgumentMarshaling, error) { if err != nil { return nil, fmt.Errorf("failed to assemble components: %v", err) } - arguments = append(arguments, ArgumentMarshaling{name, "tuple", "tuple", subArgs, false}) + tupleType := "tuple" + if len(subArgs) != 0 && subArgs[len(subArgs)-1].Type == "[]" { + subArgs = subArgs[:len(subArgs)-1] + tupleType = "tuple[]" + } + arguments = append(arguments, ArgumentMarshaling{name, tupleType, tupleType, subArgs, false}) } else { return nil, fmt.Errorf("failed to assemble args: unexpected type %T", arg) } diff --git a/accounts/abi/selector_parser_test.go b/accounts/abi/selector_parser_test.go index 9720c9d5308e..b5be6a3897de 100644 --- a/accounts/abi/selector_parser_test.go +++ b/accounts/abi/selector_parser_test.go @@ -16,6 +16,8 @@ func TestParseSelector(t *testing.T) { result = append(result, ArgumentMarshaling{name, typeName, typeName, nil, false}) } else if components, ok := typeOrComponents.([]ArgumentMarshaling); ok { result = append(result, ArgumentMarshaling{name, "tuple", "tuple", components, false}) + } else if components, ok := typeOrComponents.([][]ArgumentMarshaling); ok { + result = append(result, ArgumentMarshaling{name, "tuple[]", "tuple[]", components[0], false}) } else { log.Fatalf("unexpected type %T", typeOrComponents) } @@ -34,6 +36,13 @@ func TestParseSelector(t *testing.T) { {"singleNest(bytes32,uint8,(uint256,uint256),address)", "singleNest", mkType("bytes32", "uint8", mkType("uint256", "uint256"), "address")}, {"multiNest(address,(uint256[],uint256),((address,bytes32),uint256))", "multiNest", mkType("address", mkType("uint256[]", "uint256"), mkType(mkType("address", "bytes32"), "uint256"))}, + {"arrayNest((uint256,uint256)[],bytes32)", "arrayNest", mkType([][]ArgumentMarshaling{mkType("uint256", "uint256")}, "bytes32")}, + {"multiArrayNest((uint256,uint256)[],(uint256,uint256)[])", "multiArrayNest", + mkType([][]ArgumentMarshaling{mkType("uint256", "uint256")}, [][]ArgumentMarshaling{mkType("uint256", "uint256")})}, + {"singleArrayNestAndArray((uint256,uint256)[],bytes32[])", "singleArrayNestAndArray", + mkType([][]ArgumentMarshaling{mkType("uint256", "uint256")}, "bytes32[]")}, + {"singleArrayNestWithArrayAndArray((uint256[],address[2],uint8[4][][5])[],bytes32[])", "singleArrayNestWithArrayAndArray", + mkType([][]ArgumentMarshaling{mkType("uint256[]", "address[2]", "uint8[4][][5]")}, "bytes32[]")}, } for i, tt := range tests { selector, err := ParseSelector(tt.input)