-
Notifications
You must be signed in to change notification settings - Fork 13
/
keeper.go
112 lines (95 loc) · 2.75 KB
/
keeper.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
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
package keeper
import (
"fmt"
"math/big"
errorsmod "cosmossdk.io/errors"
sdk "github.com/cosmos/cosmos-sdk/types"
"github.com/ethereum/go-ethereum/accounts/abi"
"github.com/ethereum/go-ethereum/common"
ethtypes "github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/core/vm"
evmkeeper "github.com/evmos/ethermint/x/evm/keeper"
"github.com/evmos/ethermint/x/evm/types"
fxserverconfig "github.com/functionx/fx-core/v4/server/config"
fxtypes "github.com/functionx/fx-core/v4/types"
fxevmtypes "github.com/functionx/fx-core/v4/x/evm/types"
)
type Keeper struct {
*evmkeeper.Keeper
// access to account state
accountKeeper fxevmtypes.AccountKeeper
// has evm hooks
hasHooks bool
module common.Address
}
func NewKeeper(ek *evmkeeper.Keeper, ak fxevmtypes.AccountKeeper) *Keeper {
ctx := sdk.Context{}.WithChainID(fxtypes.ChainIdWithEIP155())
ek.WithChainID(ctx)
addr := ak.GetModuleAddress(types.ModuleName)
if addr == nil {
panic(fmt.Sprintf("%s module account has not been set", types.ModuleName))
}
return &Keeper{
Keeper: ek,
accountKeeper: ak,
module: common.BytesToAddress(addr),
}
}
// SetHooks sets the hooks for the EVM module
// It should be called only once during initialization, it panic if called more than once.
func (k *Keeper) SetHooks(eh types.EvmHooks) *Keeper {
if eh == nil {
panic("cannot to set nil evm hook")
}
k.Keeper.SetHooks(eh)
k.hasHooks = true
return k
}
// CallEVMWithoutGas performs a smart contract method call using contract data without gas
func (k *Keeper) CallEVMWithoutGas(
ctx sdk.Context,
from common.Address,
contract *common.Address,
data []byte,
commit bool,
) (*types.MsgEthereumTxResponse, error) {
gasMeter := ctx.GasMeter()
ctx = ctx.WithGasMeter(sdk.NewInfiniteGasMeter())
nonce, err := k.accountKeeper.GetSequence(ctx, from.Bytes())
if err != nil {
return nil, err
}
gasLimit := fxserverconfig.DefaultGasCap
params := ctx.ConsensusParams()
if params != nil && params.Block != nil && params.Block.MaxGas > 0 {
gasLimit = uint64(params.Block.MaxGas)
}
msg := ethtypes.NewMessage(
from,
contract,
nonce,
big.NewInt(0), // amount
gasLimit, // gasLimit
big.NewInt(0), // gasFeeCap
big.NewInt(0), // gasTipCap
big.NewInt(0), // gasPrice
data,
ethtypes.AccessList{}, // AccessList
!commit, // isFake
)
res, err := k.ApplyMessage(ctx, msg, types.NewNoOpTracer(), commit)
if err != nil {
return nil, err
}
if res.Failed() {
errStr := res.VmError
if res.VmError == vm.ErrExecutionReverted.Error() {
if reason, err := abi.UnpackRevert(common.CopyBytes(res.Ret)); err == nil {
errStr = reason
}
}
return res, errorsmod.Wrap(types.ErrVMExecution, errStr)
}
ctx.WithGasMeter(gasMeter)
return res, nil
}