Skip to content

Commit 169f8eb

Browse files
darrenvechaingballet
authored andcommitted
accounts/abi: support unpacking solidity errors (ethereum#30738)
This PR adds the error fragments to `func (abi ABI) getArguments` which allows typed decoding of errors.
1 parent f5d97cd commit 169f8eb

File tree

2 files changed

+38
-2
lines changed

2 files changed

+38
-2
lines changed

accounts/abi/abi.go

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -84,7 +84,7 @@ func (abi ABI) Pack(name string, args ...interface{}) ([]byte, error) {
8484

8585
func (abi ABI) getArguments(name string, data []byte) (Arguments, error) {
8686
// since there can't be naming collisions with contracts and events,
87-
// we need to decide whether we're calling a method or an event
87+
// we need to decide whether we're calling a method, event or an error
8888
var args Arguments
8989
if method, ok := abi.Methods[name]; ok {
9090
if len(data)%32 != 0 {
@@ -95,8 +95,11 @@ func (abi ABI) getArguments(name string, data []byte) (Arguments, error) {
9595
if event, ok := abi.Events[name]; ok {
9696
args = event.Inputs
9797
}
98+
if err, ok := abi.Errors[name]; ok {
99+
args = err.Inputs
100+
}
98101
if args == nil {
99-
return nil, fmt.Errorf("abi: could not locate named method or event: %s", name)
102+
return nil, fmt.Errorf("abi: could not locate named method, event or error: %s", name)
100103
}
101104
return args, nil
102105
}

accounts/abi/abi_test.go

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@ import (
2929
"github.com/ethereum/go-ethereum/common"
3030
"github.com/ethereum/go-ethereum/common/math"
3131
"github.com/ethereum/go-ethereum/crypto"
32+
"github.com/ethereum/go-ethereum/internal/testrand"
3233
)
3334

3435
const jsondata = `
@@ -317,6 +318,38 @@ func TestCustomErrors(t *testing.T) {
317318
check("MyError", "MyError(uint256)")
318319
}
319320

321+
func TestCustomErrorUnpackIntoInterface(t *testing.T) {
322+
t.Parallel()
323+
errorName := "MyError"
324+
json := fmt.Sprintf(`[{"inputs":[{"internalType":"address","name":"sender","type":"address"},{"internalType":"uint256","name":"balance","type":"uint256"}],"name":"%s","type":"error"}]`, errorName)
325+
abi, err := JSON(strings.NewReader(json))
326+
if err != nil {
327+
t.Fatal(err)
328+
}
329+
type MyError struct {
330+
Sender common.Address
331+
Balance *big.Int
332+
}
333+
334+
sender := testrand.Address()
335+
balance := new(big.Int).SetBytes(testrand.Bytes(8))
336+
encoded, err := abi.Errors[errorName].Inputs.Pack(sender, balance)
337+
if err != nil {
338+
t.Fatal(err)
339+
}
340+
result := MyError{}
341+
err = abi.UnpackIntoInterface(&result, errorName, encoded)
342+
if err != nil {
343+
t.Fatal(err)
344+
}
345+
if result.Sender != sender {
346+
t.Errorf("expected %x got %x", sender, result.Sender)
347+
}
348+
if result.Balance.Cmp(balance) != 0 {
349+
t.Errorf("expected %v got %v", balance, result.Balance)
350+
}
351+
}
352+
320353
func TestMultiPack(t *testing.T) {
321354
t.Parallel()
322355
abi, err := JSON(strings.NewReader(jsondata))

0 commit comments

Comments
 (0)