Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 14 additions & 0 deletions accounts/abi/abi.go
Original file line number Diff line number Diff line change
Expand Up @@ -222,6 +222,20 @@ func (abi *ABI) EventByID(topic common.Hash) (*Event, error) {
return nil, fmt.Errorf("no event with id: %#x", topic.Hex())
}

// ErrorById looks up an error by the 4-byte id,
// returns nil if none found.
func (abi *ABI) ErrorById(sigdata []byte) (*Error, error) {
if len(sigdata) < 4 {
return nil, fmt.Errorf("data too short (%d bytes) for abi error lookup", len(sigdata))
}
for _, errABI := range abi.Errors {
if bytes.Equal(errABI.ID, sigdata[:4]) {

@fjl fjl May 16, 2023

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I wonder why you changed the ID field to []byte. Might be better to:

  • change the type of the sigdata parameter to [4]byte
  • do the check like bytes.Equal(errABI.ID[:4], sigdata[:])

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I implement it in the same way as MethodById did. I'll modify it if [4]byte is better.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In my opinion, []byte is better because I can use ErrorData as an input to find abi.Error.

return &errABI, nil
}
}
return nil, fmt.Errorf("no error with id: %#x", sigdata[:4])
}

// HasFallback returns an indicator whether a fallback function is included.
func (abi *ABI) HasFallback() bool {
return abi.Fallback.Type == Fallback
Expand Down
36 changes: 36 additions & 0 deletions accounts/abi/abi_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -1057,6 +1057,42 @@ func TestABI_EventById(t *testing.T) {
}
}

func TestABI_ErrorById(t *testing.T) {
abi, err := JSON(strings.NewReader(`[
{"inputs":[{"internalType":"uint256","name":"x","type":"uint256"}],"name":"MyError1","type":"error"},
{"inputs":[{"components":[{"internalType":"uint256","name":"a","type":"uint256"},{"internalType":"string","name":"b","type":"string"},{"internalType":"address","name":"c","type":"address"}],"internalType":"struct MyError.MyStruct","name":"x","type":"tuple"},{"internalType":"address","name":"y","type":"address"},{"components":[{"internalType":"uint256","name":"a","type":"uint256"},{"internalType":"string","name":"b","type":"string"},{"internalType":"address","name":"c","type":"address"}],"internalType":"struct MyError.MyStruct","name":"z","type":"tuple"}],"name":"MyError2","type":"error"},
{"inputs":[{"internalType":"uint256[]","name":"x","type":"uint256[]"}],"name":"MyError3","type":"error"}
]`))
if err != nil {
t.Fatal(err)
}
for name, m := range abi.Errors {
a := fmt.Sprintf("%v", &m)
m2, err := abi.ErrorById(m.ID)
if err != nil {
t.Fatalf("Failed to look up ABI error: %v", err)
}
b := fmt.Sprintf("%v", m2)
if a != b {
t.Errorf("Error %v (id %x) not 'findable' by id in ABI", name, m.ID)
}
}
// test unsuccessful lookups
if _, err = abi.ErrorById(crypto.Keccak256()); err == nil {
t.Error("Expected error: no error with this id")
}
// Also test empty
if _, err := abi.ErrorById([]byte{0x00}); err == nil {
t.Errorf("Expected error, too short to decode data")
}
if _, err := abi.ErrorById([]byte{}); err == nil {
t.Errorf("Expected error, too short to decode data")
}
if _, err := abi.ErrorById(nil); err == nil {
t.Errorf("Expected error, nil is short to decode data")
}
}

// TestDoubleDuplicateMethodNames checks that if transfer0 already exists, there won't be a name
// conflict and that the second transfer method will be renamed transfer1.
func TestDoubleDuplicateMethodNames(t *testing.T) {
Expand Down
7 changes: 3 additions & 4 deletions accounts/abi/error.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,6 @@ import (
"fmt"
"strings"

"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/crypto"
)

Expand All @@ -38,7 +37,7 @@ type Error struct {

// ID returns the canonical representation of the error's signature used by the
// abi definition to identify event names and types.
ID common.Hash
ID []byte
}

func NewError(name string, inputs Arguments) Error {
Expand Down Expand Up @@ -67,7 +66,7 @@ func NewError(name string, inputs Arguments) Error {

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)))
id := crypto.Keccak256([]byte(sig))[:4]

return Error{
Name: name,
Expand All @@ -78,7 +77,7 @@ func NewError(name string, inputs Arguments) Error {
}
}

func (e *Error) String() string {
func (e Error) String() string {
return e.str
}

Expand Down