Skip to content

Commit f9a9db6

Browse files
committed
full support for errors with working test
1 parent 326da99 commit f9a9db6

File tree

7 files changed

+54
-12
lines changed

7 files changed

+54
-12
lines changed

accounts/abi/bind/source2.go.tpl

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -156,10 +156,10 @@ var (
156156
{{$i := 0}}
157157
{{range $k, $v := .Errors}}
158158
{{ if eq $i 0 }}
159-
if val, err := _{{$contract.Type}}.Unpack{{.Normalized.Name}}Error(raw); err != nil {
159+
if val, err := _{{$contract.Type}}.Unpack{{.Normalized.Name}}Error(raw); err == nil {
160160
return val
161161
{{ else }}
162-
} else if val, err := _{{$contract.Type}}.Unpack{{.Normalized.Name}}Error(raw); err != nil {
162+
} else if val, err := _{{$contract.Type}}.Unpack{{.Normalized.Name}}Error(raw); err == nil {
163163
return val
164164
{{ end -}}
165165
{{$i = add $i 1}}

accounts/abi/bind/v2/internal/solc_errors/bindings.go

Lines changed: 2 additions & 2 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.
Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
{"contracts":{"contract.sol:C":{"abi":[{"inputs":[{"internalType":"uint256","name":"arg1","type":"uint256"},{"internalType":"uint256","name":"arg2","type":"uint256"},{"internalType":"uint256","name":"arg3","type":"uint256"},{"internalType":"bool","name":"arg4","type":"bool"}],"name":"BadThing","type":"error"},{"inputs":[{"internalType":"uint256","name":"arg1","type":"uint256"},{"internalType":"uint256","name":"arg2","type":"uint256"},{"internalType":"uint256","name":"arg3","type":"uint256"},{"internalType":"uint256","name":"arg4","type":"uint256"}],"name":"BadThing2","type":"error"},{"inputs":[],"name":"Bar","outputs":[],"stateMutability":"pure","type":"function"},{"inputs":[],"name":"Foo","outputs":[],"stateMutability":"pure","type":"function"}],"bin":"6080604052348015600e575f80fd5b506101c58061001c5f395ff3fe608060405234801561000f575f80fd5b5060043610610034575f3560e01c8063b0a378b014610038578063bfb4ebcf14610042575b5f80fd5b61004061004c565b005b61004a610092565b005b5f6001600260036040517fd233a24f00000000000000000000000000000000000000000000000000000000815260040161008994939291906100ef565b60405180910390fd5b5f600160025f6040517fbb6a82f10000000000000000000000000000000000000000000000000000000081526004016100ce949392919061014c565b60405180910390fd5b5f819050919050565b6100e9816100d7565b82525050565b5f6080820190506101025f8301876100e0565b61010f60208301866100e0565b61011c60408301856100e0565b61012960608301846100e0565b95945050505050565b5f8115159050919050565b61014681610132565b82525050565b5f60808201905061015f5f8301876100e0565b61016c60208301866100e0565b61017960408301856100e0565b610186606083018461013d565b9594505050505056fea26469706673582212203f89da086f6d7e52e75f82a20ebbf7337f166a6dbae309180c8bb95e1a157e6e64736f6c634300081a0033"}},"version":"0.8.26+commit.8a97fa7a.Darwin.appleclang"}
1+
{"contracts":{"contract.sol:C":{"abi":[{"inputs":[{"internalType":"uint256","name":"arg1","type":"uint256"},{"internalType":"uint256","name":"arg2","type":"uint256"},{"internalType":"uint256","name":"arg3","type":"uint256"},{"internalType":"bool","name":"arg4","type":"bool"}],"name":"BadThing","type":"error"},{"inputs":[{"internalType":"uint256","name":"arg1","type":"uint256"},{"internalType":"uint256","name":"arg2","type":"uint256"},{"internalType":"uint256","name":"arg3","type":"uint256"},{"internalType":"uint256","name":"arg4","type":"uint256"}],"name":"BadThing2","type":"error"},{"inputs":[],"name":"Bar","outputs":[],"stateMutability":"pure","type":"function"},{"inputs":[],"name":"Foo","outputs":[],"stateMutability":"pure","type":"function"}],"bin":"6080604052348015600e575f80fd5b506101c58061001c5f395ff3fe608060405234801561000f575f80fd5b5060043610610034575f3560e01c8063b0a378b014610038578063bfb4ebcf14610042575b5f80fd5b61004061004c565b005b61004a610092565b005b5f6001600260036040517fd233a24f00000000000000000000000000000000000000000000000000000000815260040161008994939291906100ef565b60405180910390fd5b5f600160025f6040517fbb6a82f10000000000000000000000000000000000000000000000000000000081526004016100ce949392919061014c565b60405180910390fd5b5f819050919050565b6100e9816100d7565b82525050565b5f6080820190506101025f8301876100e0565b61010f60208301866100e0565b61011c60408301856100e0565b61012960608301846100e0565b95945050505050565b5f8115159050919050565b61014681610132565b82525050565b5f60808201905061015f5f8301876100e0565b61016c60208301866100e0565b61017960408301856100e0565b610186606083018461013d565b9594505050505056fea264697066735822122043974fbdd5c75b36bb8fe9dd68c112de4d094a0d8626d74e03edd5e48f18118164736f6c634300081a0033"},"contract.sol:C2":{"abi":[{"inputs":[{"internalType":"uint256","name":"arg1","type":"uint256"},{"internalType":"uint256","name":"arg2","type":"uint256"},{"internalType":"uint256","name":"arg3","type":"uint256"},{"internalType":"bool","name":"arg4","type":"bool"}],"name":"BadThing","type":"error"},{"inputs":[],"name":"Foo","outputs":[],"stateMutability":"pure","type":"function"}],"bin":"6080604052348015600e575f80fd5b506101148061001c5f395ff3fe6080604052348015600e575f80fd5b50600436106026575f3560e01c8063bfb4ebcf14602a575b5f80fd5b60306032565b005b5f600160025f6040517fbb6a82f1000000000000000000000000000000000000000000000000000000008152600401606c949392919060a3565b60405180910390fd5b5f819050919050565b6085816075565b82525050565b5f8115159050919050565b609d81608b565b82525050565b5f60808201905060b45f830187607e565b60bf6020830186607e565b60ca6040830185607e565b60d560608301846096565b9594505050505056fea264697066735822122073ad1e2383066bba44481ee5aaadd9a60a3e08e602e13ebf1c67c51ef47d191564736f6c634300081a0033"}},"version":"0.8.26+commit.8a97fa7a.Darwin.appleclang"}

accounts/abi/bind/v2/internal/solc_errors/contract.sol

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,4 +21,16 @@ contract C {
2121
arg4: uint256(3)
2222
});
2323
}
24+
}
25+
26+
// purpose of this is to test that generation of metadata for contract that emits one error produces valid Go code
27+
contract C2 {
28+
function Foo() public pure {
29+
revert BadThing({
30+
arg1: uint256(0),
31+
arg2: uint256(1),
32+
arg3: uint256(2),
33+
arg4: false
34+
});
35+
}
2436
}

accounts/abi/bind/v2/lib.go

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -373,3 +373,15 @@ func Call[T any](instance *ContractInstance, opts *bind.CallOpts, packedInput []
373373
}
374374
return unpack(packedOutput)
375375
}
376+
377+
/*
378+
func UnpackError(metadata *bind.MetaData, raw []byte) (any, error) {
379+
fmt.Printf("raw is %x\n", raw[0:4])
380+
errType := metadata.Errors[fmt.Sprintf("%x", raw[0:4])]
381+
abi, _ := metadata.GetAbi() // TODO: check error here?
382+
res := reflect.New(errType).Interface()
383+
fmt.Printf("err type name is %s\n", errType.Name())
384+
err := abi.UnpackIntoInterface(&res, errType.Name(), raw)
385+
return res, err
386+
}
387+
*/

accounts/abi/bind/v2/lib_test.go

Lines changed: 17 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@ import (
3232
"github.com/ethereum/go-ethereum/core/types"
3333
"github.com/ethereum/go-ethereum/crypto"
3434
"github.com/ethereum/go-ethereum/eth/ethconfig"
35+
"github.com/ethereum/go-ethereum/ethclient"
3536
"github.com/ethereum/go-ethereum/ethclient/simulated"
3637
"github.com/ethereum/go-ethereum/node"
3738
"github.com/ethereum/go-ethereum/params"
@@ -396,18 +397,32 @@ func TestErrors(t *testing.T) {
396397
t.Fatalf("WaitDeployed failed %v", err)
397398
}
398399

400+
ctrct, _ := solc_errors.NewC()
401+
399402
var packedInput []byte
400403
opts := &bind.CallOpts{
401404
From: res.Addrs[solc_errors.CMetaData.Pattern],
402405
}
406+
packedInput, _ = ctrct.PackFoo()
407+
403408
instance := ContractInstance{res.Addrs[solc_errors.CMetaData.Pattern], backend}
404-
_, err := Call[struct{}](&instance, opts, packedInput, func(packed []byte) (*struct{}, error) { return nil, nil })
409+
_, err = Call[struct{}](&instance, opts, packedInput, func(packed []byte) (*struct{}, error) { return nil, nil })
405410
if err == nil {
406411
t.Fatalf("expected call to fail")
407412
}
408-
413+
raw, hasRevertErrorData := ethclient.RevertErrorData(err)
414+
if !hasRevertErrorData {
415+
t.Fatalf("expected call error to contain revert error data.")
416+
}
417+
unpackedErr := ctrct.UnpackError(raw)
418+
if unpackedErr == nil {
419+
t.Fatalf("expected to unpack error")
420+
}
421+
// TODO: check anything about the error?
409422
}
410423

424+
// TODO: this test will pass if the code is changed but not compiled to a combined-abi.json.
425+
// Not really possible to test this without including solc in the path when running CI.
411426
func TestBindingGeneration(t *testing.T) {
412427
matches, _ := filepath.Glob("internal/*")
413428
var dirs []string

accounts/abi/error.go

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,8 @@ type Error struct {
3838
// ID returns the canonical representation of the error's signature used by the
3939
// abi definition to identify event names and types.
4040
ID common.Hash
41+
42+
Selector string
4143
}
4244

4345
func NewError(name string, inputs Arguments) Error {
@@ -69,11 +71,12 @@ func NewError(name string, inputs Arguments) Error {
6971
id := common.BytesToHash(crypto.Keccak256([]byte(sig)))
7072

7173
return Error{
72-
Name: name,
73-
Inputs: inputs,
74-
str: str,
75-
Sig: sig,
76-
ID: id,
74+
Name: name,
75+
Inputs: inputs,
76+
str: str,
77+
Sig: sig,
78+
ID: id,
79+
Selector: fmt.Sprintf("%x", id[0:4]),
7780
}
7881
}
7982

0 commit comments

Comments
 (0)