From 46e872a8ce603ef65fcb6176e2c7af7a4c29e9d3 Mon Sep 17 00:00:00 2001 From: Marius van der Wijden Date: Tue, 6 Jul 2021 15:05:10 +0200 Subject: [PATCH] accounts/abi: events can't be overloaded --- accounts/abi/abi.go | 3 +-- accounts/abi/bind/bind_test.go | 16 +++++++++---- accounts/abi/error.go | 41 +++++++++++++++++++++------------- 3 files changed, 38 insertions(+), 22 deletions(-) diff --git a/accounts/abi/abi.go b/accounts/abi/abi.go index 93c168c0610d7..cd2f4d7978bd1 100644 --- a/accounts/abi/abi.go +++ b/accounts/abi/abi.go @@ -187,8 +187,7 @@ func (abi *ABI) UnmarshalJSON(data []byte) error { name := overloadedName(field.Name, func(s string) bool { _, ok := abi.Events[s]; return ok }) abi.Events[name] = NewEvent(name, field.Name, field.Anonymous, field.Inputs) case "error": - name := overloadedName(field.Name, func(s string) bool { _, ok := abi.Errors[s]; return ok }) - abi.Errors[name] = NewError(name, field.Name, field.Inputs) + abi.Errors[field.Name] = NewError(field.Name, field.Inputs) default: return fmt.Errorf("abi: could not recognize type %v of field %v", field.Type, field.Name) } diff --git a/accounts/abi/bind/bind_test.go b/accounts/abi/bind/bind_test.go index 797f8e5b136f2..5a436607ce45a 100644 --- a/accounts/abi/bind/bind_test.go +++ b/accounts/abi/bind/bind_test.go @@ -1862,15 +1862,18 @@ var bindTests = []struct { ` pragma solidity >0.8.4; - contract Test { + contract NewErrors { error MyError(uint256); error MyError1(uint256); error MyError2(uint256, uint256); error MyError3(uint256 a, uint256 b, uint256 c); + function Error() public pure { + revert MyError3(1,2,3); + } } `, - []string{"0x6080604052348015600f57600080fd5b50603f80601d6000396000f3fe6080604052600080fdfea2646970667358221220313fc94775b67962460298a5e968a46aed3683e1162a713923677e23373efa6364736f6c63430008060033"}, - []string{`[{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"MyError","type":"error"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"MyError1","type":"error"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"uint256","name":"","type":"uint256"}],"name":"MyError2","type":"error"},{"inputs":[{"internalType":"uint256","name":"a","type":"uint256"},{"internalType":"uint256","name":"b","type":"uint256"},{"internalType":"uint256","name":"c","type":"uint256"}],"name":"MyError3","type":"error"}]`}, + []string{"0x6080604052348015600f57600080fd5b5060998061001e6000396000f3fe6080604052348015600f57600080fd5b506004361060285760003560e01c8063726c638214602d575b600080fd5b60336035565b005b60405163024876cd60e61b815260016004820152600260248201526003604482015260640160405180910390fdfea264697066735822122093f786a1bc60216540cd999fbb4a6109e0fef20abcff6e9107fb2817ca968f3c64736f6c63430008070033"}, + []string{`[{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"MyError","type":"error"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"MyError1","type":"error"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"uint256","name":"","type":"uint256"}],"name":"MyError2","type":"error"},{"inputs":[{"internalType":"uint256","name":"a","type":"uint256"},{"internalType":"uint256","name":"b","type":"uint256"},{"internalType":"uint256","name":"c","type":"uint256"}],"name":"MyError3","type":"error"},{"inputs":[],"name":"Error","outputs":[],"stateMutability":"pure","type":"function"}]`}, ` "math/big" @@ -1888,7 +1891,7 @@ var bindTests = []struct { ) defer sim.Close() - _, tx, _, err := DeployNewErrors(user, sim) + _, tx, contract, err := DeployNewErrors(user, sim) if err != nil { t.Fatal(err) } @@ -1897,6 +1900,11 @@ var bindTests = []struct { if err != nil { t.Error(err) } + if err := contract.Error(new(bind.CallOpts)); err == nil { + t.Fatalf("expected contract to throw error") + } + // TODO (MariusVanDerWijden unpack error using abigen + // once that is implemented `, nil, nil, diff --git a/accounts/abi/error.go b/accounts/abi/error.go index ae11ed97cef59..3d1a4877ddcd3 100644 --- a/accounts/abi/error.go +++ b/accounts/abi/error.go @@ -17,6 +17,8 @@ package abi import ( + "bytes" + "errors" "fmt" "strings" @@ -25,11 +27,9 @@ import ( ) type Error struct { - Name string - // RawName might be overloaded - RawName string - Inputs Arguments - str string + Name string + Inputs Arguments + str string // Sig contains the string signature according to the ABI spec. // e.g. event foo(uint32 a, int b) = "foo(uint32,int256)" // Please note that "int" is substitute for its canonical representation "int256" @@ -39,7 +39,7 @@ type Error struct { ID common.Hash } -func NewError(name, rawName string, inputs Arguments) Error { +func NewError(name string, inputs Arguments) Error { // sanitize inputs to remove inputs without names // and precompute string and sig representation. names := make([]string, len(inputs)) @@ -63,20 +63,29 @@ func NewError(name, rawName string, inputs Arguments) Error { types[i] = input.Type.String() } - str := fmt.Sprintf("event %v(%v)", rawName, strings.Join(names, ", ")) - sig := fmt.Sprintf("%v(%v)", rawName, strings.Join(types, ",")) + str := fmt.Sprintf("error %v(%v)", name, strings.Join(names, ", ")) + sig := fmt.Sprintf("%v(%v)", name, strings.Join(types, ",")) id := common.BytesToHash(crypto.Keccak256([]byte(sig))) return Error{ - Name: name, - RawName: rawName, - Inputs: inputs, - str: str, - Sig: sig, - ID: id, + Name: name, + Inputs: inputs, + str: str, + Sig: sig, + ID: id, } } -func (err *Error) String() string { - return err.str +func (e *Error) String() string { + return e.str +} + +func (e *Error) Unpack(data []byte) (interface{}, error) { + if len(data) < 4 { + return "", errors.New("invalid data for unpacking") + } + if !bytes.Equal(data[:4], e.ID[:4]) { + return "", errors.New("invalid data for unpacking") + } + return e.Inputs.Unpack(data[4:]) }