mirror of
https://github.com/ethereum/go-ethereum.git
synced 2026-07-18 19:00:46 +00:00
Merge ad358f990b into dddbaa4bf3
This commit is contained in:
commit
a58dd55a76
1 changed files with 93 additions and 0 deletions
|
|
@ -798,6 +798,99 @@ func ExampleRevertErrorData() {
|
|||
// message: user error
|
||||
}
|
||||
|
||||
// ExampleRevertErrorData_estimateGas shows how to get the revert reason from a
|
||||
// failed EstimateGas call. The same function works for both CallContract and
|
||||
// EstimateGas.
|
||||
func ExampleRevertErrorData_estimateGas() {
|
||||
ctx := context.Background()
|
||||
ec, _ := ethclient.DialContext(ctx, exampleNode.HTTPEndpoint())
|
||||
|
||||
contract := common.HexToAddress("290f1b36649a61e369c6276f6d29463335b4400c")
|
||||
call := ethereum.CallMsg{To: &contract, Gas: 30000}
|
||||
_, err := ec.EstimateGas(ctx, call)
|
||||
if err == nil {
|
||||
panic("EstimateGas did not return error")
|
||||
}
|
||||
|
||||
revertData, ok := ethclient.RevertErrorData(err)
|
||||
if !ok {
|
||||
panic("unpacking revert failed")
|
||||
}
|
||||
fmt.Printf("revert: %x\n", revertData)
|
||||
|
||||
message, err := abi.UnpackRevert(revertData)
|
||||
if err != nil {
|
||||
panic("parsing ABI error failed: " + err.Error())
|
||||
}
|
||||
fmt.Println("message:", message)
|
||||
|
||||
// Output:
|
||||
// revert: 08c379a00000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000a75736572206572726f72
|
||||
// message: user error
|
||||
}
|
||||
|
||||
// TestRevertErrorData verifies that RevertErrorData correctly extracts revert
|
||||
// reason bytes from both CallContract and EstimateGas errors, and returns false
|
||||
// for errors that are not EVM reverts.
|
||||
func TestRevertErrorData(t *testing.T) {
|
||||
backend, _, err := newTestBackend(nil)
|
||||
if err != nil {
|
||||
t.Fatalf("failed to create test backend: %v", err)
|
||||
}
|
||||
defer backend.Close()
|
||||
|
||||
client := ethclient.NewClient(backend.Attach())
|
||||
defer client.Close()
|
||||
|
||||
ctx := context.Background()
|
||||
msg := ethereum.CallMsg{To: &revertContractAddr, Gas: 30000}
|
||||
|
||||
// CallContract must return a revert error with extractable reason.
|
||||
_, callErr := client.CallContract(ctx, msg, nil)
|
||||
if callErr == nil {
|
||||
t.Fatal("expected CallContract to fail on reverting contract")
|
||||
}
|
||||
callData, ok := ethclient.RevertErrorData(callErr)
|
||||
if !ok {
|
||||
t.Fatalf("RevertErrorData returned false for CallContract error: %v", callErr)
|
||||
}
|
||||
callReason, err := abi.UnpackRevert(callData)
|
||||
if err != nil {
|
||||
t.Fatalf("failed to unpack CallContract revert reason: %v", err)
|
||||
}
|
||||
if callReason != "user error" {
|
||||
t.Fatalf("unexpected CallContract revert reason: %q", callReason)
|
||||
}
|
||||
|
||||
// EstimateGas must return a revert error with the same extractable reason.
|
||||
_, gasErr := client.EstimateGas(ctx, msg)
|
||||
if gasErr == nil {
|
||||
t.Fatal("expected EstimateGas to fail on reverting contract")
|
||||
}
|
||||
gasData, ok := ethclient.RevertErrorData(gasErr)
|
||||
if !ok {
|
||||
t.Fatalf("RevertErrorData returned false for EstimateGas error: %v", gasErr)
|
||||
}
|
||||
gasReason, err := abi.UnpackRevert(gasData)
|
||||
if err != nil {
|
||||
t.Fatalf("failed to unpack EstimateGas revert reason: %v", err)
|
||||
}
|
||||
if gasReason != "user error" {
|
||||
t.Fatalf("unexpected EstimateGas revert reason: %q", gasReason)
|
||||
}
|
||||
|
||||
// Revert data from CallContract and EstimateGas must be identical.
|
||||
if !bytes.Equal(callData, gasData) {
|
||||
t.Errorf("revert data mismatch: CallContract=%x, EstimateGas=%x", callData, gasData)
|
||||
}
|
||||
|
||||
// A plain error (non-revert) must not be decoded as revert data.
|
||||
_, ok = ethclient.RevertErrorData(errors.New("not a revert"))
|
||||
if ok {
|
||||
t.Fatal("RevertErrorData returned true for a plain non-revert error")
|
||||
}
|
||||
}
|
||||
|
||||
func TestSimulateV1(t *testing.T) {
|
||||
backend, _, err := newTestBackend(nil)
|
||||
if err != nil {
|
||||
|
|
|
|||
Loading…
Reference in a new issue