/
error_from_block.go
51 lines (46 loc) 路 1.8 KB
/
error_from_block.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
// Copyright 2023 The AthanorLabs/atomic-swap Authors
// SPDX-License-Identifier: LGPL-3.0-only
package block
import (
"context"
"fmt"
"github.com/ethereum/go-ethereum"
"github.com/ethereum/go-ethereum/core"
ethtypes "github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/ethclient"
)
// ErrorFromBlock returns the error for why a transaction was reverted when mined.
// Normally these errors are detected when creating the transaction, as the contract
// call is simulated to estimate gas, but the state is different in the mined block
// and the transaction can fail (losing gas) after it already went out to the network.
// In this case, we simulate the call using the mined block to extract the error.
func ErrorFromBlock(ctx context.Context, ec *ethclient.Client, receipt *ethtypes.Receipt) error {
tx, err := ec.TransactionInBlock(ctx, receipt.BlockHash, receipt.TransactionIndex)
if err != nil {
return fmt.Errorf("unable to determine error in mined block, %w", err)
}
chainID, err := ec.ChainID(ctx)
if err != nil {
return fmt.Errorf("unable to determine error in mined block, %w", err)
}
txMessage, err := core.TransactionToMessage(tx, ethtypes.LatestSignerForChainID(chainID), nil)
if err != nil {
return fmt.Errorf("unable to determine error in mined block, %w", err)
}
callMessage := ethereum.CallMsg{
From: txMessage.From,
To: txMessage.To,
Gas: txMessage.GasLimit,
GasPrice: txMessage.GasPrice,
GasFeeCap: txMessage.GasFeeCap,
GasTipCap: txMessage.GasTipCap,
Value: txMessage.Value,
Data: txMessage.Data,
AccessList: txMessage.AccessList,
}
_, err = ec.CallContract(context.Background(), callMessage, receipt.BlockNumber)
if err == nil {
return fmt.Errorf("unable to determine error in mined block")
}
return err
}