diff --git a/x/evm/keeper/gas.go b/x/evm/keeper/gas.go index e6518cc83b..26b986abc2 100644 --- a/x/evm/keeper/gas.go +++ b/x/evm/keeper/gas.go @@ -18,6 +18,7 @@ package keeper import ( "math/big" + "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/core" "github.com/ethereum/go-ethereum/params" @@ -46,6 +47,10 @@ func (k *Keeper) GetEthIntrinsicGas(ctx sdk.Context, msg core.Message, cfg *para func (k *Keeper) RefundGas(ctx sdk.Context, msg core.Message, leftoverGas uint64, denom string) error { // Return EVM tokens for remaining gas, exchanged at the original rate. remaining := new(big.Int).Mul(new(big.Int).SetUint64(leftoverGas), msg.GasPrice()) + feePayer := msg.From().Bytes() + if m,ok := msg.(types.Message); ok { + feePayer = common.HexToAddress(m.FeePayer).Bytes() + } switch remaining.Sign() { case -1: @@ -57,7 +62,7 @@ func (k *Keeper) RefundGas(ctx sdk.Context, msg core.Message, leftoverGas uint64 // refund to sender from the fee collector module account, which is the escrow account in charge of collecting tx fees - err := k.bankKeeper.SendCoinsFromModuleToAccount(ctx, authtypes.FeeCollectorName, msg.From().Bytes(), refundedCoins) + err := k.bankKeeper.SendCoinsFromModuleToAccount(ctx, authtypes.FeeCollectorName, feePayer, refundedCoins) if err != nil { err = errorsmod.Wrapf(errortypes.ErrInsufficientFunds, "fee collector account failed to refund fees: %s", err.Error()) return errorsmod.Wrapf(err, "failed to refund %d leftover gas (%s)", leftoverGas, refundedCoins.String()) diff --git a/x/evm/keeper/keeper.go b/x/evm/keeper/keeper.go index ac947247ac..e36f4c6ba9 100644 --- a/x/evm/keeper/keeper.go +++ b/x/evm/keeper/keeper.go @@ -1,4 +1,4 @@ -// Copyright 2021 Evmos Foundation +// Package keeper Copyright 2021 Evmos Foundation // This file is part of Evmos' Ethermint library. // // The Ethermint library is free software: you can redistribute it and/or modify @@ -78,6 +78,9 @@ type Keeper struct { evmConstructor evm.Constructor // Legacy subspace ss paramstypes.Subspace + + // options for the EVM + opts types.Options } // NewKeeper generates new evm module keeper @@ -118,6 +121,7 @@ func NewKeeper( evmConstructor: evmConstructor, tracer: tracer, ss: ss, + opts: types.DefaultOptions(), } } @@ -126,6 +130,12 @@ func (k Keeper) Logger(ctx sdk.Context) log.Logger { return ctx.Logger().With("module", types.ModuleName) } +// WithOptions sets the options to the keeper +func (k *Keeper) WithOptions(opts types.Options) *Keeper{ + k.opts = opts + return k +} + // WithChainID sets the chain id to the local variable in the keeper func (k *Keeper) WithChainID(ctx sdk.Context) { chainID, err := ethermint.ParseChainID(ctx.ChainID()) diff --git a/x/evm/keeper/state_transition.go b/x/evm/keeper/state_transition.go index a13d2cfd43..db650ba9ee 100644 --- a/x/evm/keeper/state_transition.go +++ b/x/evm/keeper/state_transition.go @@ -1,4 +1,4 @@ -// Copyright 2021 Evmos Foundation +// Package keeper Copyright 2021 Evmos Foundation // This file is part of Evmos' Ethermint library. // // The Ethermint library is free software: you can redistribute it and/or modify @@ -44,7 +44,6 @@ import ( // NOTE: the RANDOM opcode is currently not supported since it requires // RANDAO implementation. See https://github.com/evmos/ethermint/pull/1520#pullrequestreview-1200504697 // for more information. - func (k *Keeper) NewEVM( ctx sdk.Context, msg core.Message, @@ -53,8 +52,8 @@ func (k *Keeper) NewEVM( stateDB vm.StateDB, ) evm.EVM { blockCtx := vm.BlockContext{ - CanTransfer: core.CanTransfer, - Transfer: core.Transfer, + CanTransfer: k.opts.CanTransfer, + Transfer: k.opts.Transfer, GetHash: k.GetHashFn(ctx), Coinbase: cfg.CoinBase, GasLimit: ethermint.BlockGasLimit(ctx), diff --git a/x/evm/types/extensions.go b/x/evm/types/extensions.go new file mode 100644 index 0000000000..bce22ab5d8 --- /dev/null +++ b/x/evm/types/extensions.go @@ -0,0 +1,28 @@ +package types + +import ( + "github.com/ethereum/go-ethereum/core" + "github.com/ethereum/go-ethereum/core/vm" +) + +var _ core.Message = (*Message)(nil) + +// Options for the EVM module +type Options struct { + CanTransfer vm.CanTransferFunc + Transfer vm.TransferFunc +} + +// DefaultOptions for the EVM module +func DefaultOptions() Options { + return Options{ + CanTransfer: core.CanTransfer, + Transfer: core.Transfer, + } +} + +// Message wrap the core.Message interface. +type Message struct { + core.Message + FeePayer string +} \ No newline at end of file diff --git a/x/evm/types/msg.go b/x/evm/types/msg.go index fbe5623769..1e6492335b 100644 --- a/x/evm/types/msg.go +++ b/x/evm/types/msg.go @@ -376,7 +376,14 @@ func (msg MsgEthereumTx) AsMessage(signer ethtypes.Signer, baseFee *big.Int) (co false, ) - return ethMsg, nil + if msg.FeePayer == "" { + return ethMsg, nil + } + + return Message{ + Message: ethMsg, + FeePayer: msg.FeePayer, + }, nil } // GetSender extracts the sender address from the signature values using the latest signer for the given chainID.