diff --git a/app/ante/ante_test.go b/app/ante/ante_test.go index 4aa20a9634..fa1e20b08e 100644 --- a/app/ante/ante_test.go +++ b/app/ante/ante_test.go @@ -69,7 +69,7 @@ func (suite *AnteTestSuite) TestAnteHandler() { suite.Require().NoError(acc.SetSequence(1)) suite.app.AccountKeeper.SetAccount(suite.ctx, acc) - suite.app.EvmKeeper.SetBalance(suite.ctx, addr, big.NewInt(10000000000)) + suite.app.EvmKeeper.SetBalance(suite.ctx, addr, big.NewInt(10000000000), evmtypes.DefaultEVMDenom) suite.app.FeeMarketKeeper.SetBaseFee(suite.ctx, big.NewInt(100)) } @@ -1206,7 +1206,7 @@ func (suite *AnteTestSuite) TestAnteHandlerWithDynamicTxFee() { suite.app.AccountKeeper.SetAccount(suite.ctx, acc) suite.ctx = suite.ctx.WithIsCheckTx(tc.checkTx).WithIsReCheckTx(tc.reCheckTx) - suite.app.EvmKeeper.SetBalance(suite.ctx, addr, big.NewInt((ethparams.InitialBaseFee+10)*100000)) + suite.app.EvmKeeper.SetBalance(suite.ctx, addr, big.NewInt((ethparams.InitialBaseFee+10)*100000), evmtypes.DefaultEVMDenom) _, err := suite.anteHandler(suite.ctx, tc.txFn(), false) if tc.expPass { suite.Require().NoError(err) @@ -1335,7 +1335,7 @@ func (suite *AnteTestSuite) TestAnteHandlerWithParams() { suite.app.AccountKeeper.SetAccount(suite.ctx, acc) suite.ctx = suite.ctx.WithIsCheckTx(true) - suite.app.EvmKeeper.SetBalance(suite.ctx, addr, big.NewInt((ethparams.InitialBaseFee+10)*100000)) + suite.app.EvmKeeper.SetBalance(suite.ctx, addr, big.NewInt((ethparams.InitialBaseFee+10)*100000), evmtypes.DefaultEVMDenom) _, err := suite.anteHandler(suite.ctx, tc.txFn(), false) if tc.expErr == nil { suite.Require().NoError(err) diff --git a/app/ante/eip712.go b/app/ante/eip712.go index 8ea3aa7447..a725289453 100644 --- a/app/ante/eip712.go +++ b/app/ante/eip712.go @@ -52,10 +52,15 @@ func init() { // transactions, as defined by the presence of an ExtensionOptionsWeb3Tx extension. func NewLegacyCosmosAnteHandlerEip712(ctx sdk.Context, options HandlerOptions, extra ...sdk.AnteDecorator) sdk.AnteHandler { evmParams := options.EvmKeeper.GetParams(ctx) + feemarketParams := options.FeeMarketKeeper.GetParams(ctx) evmDenom := evmParams.EvmDenom chainID := options.EvmKeeper.ChainID() chainCfg := evmParams.GetChainConfig() ethCfg := chainCfg.EthereumConfig(chainID) + var txFeeChecker authante.TxFeeChecker + if options.DynamicFeeChecker { + txFeeChecker = NewDynamicFeeChecker(ethCfg, &evmParams, &feemarketParams) + } decorators := []sdk.AnteDecorator{ RejectMessagesDecorator{}, // reject MsgEthereumTxs // disable the Msg types that cannot be included on an authz.MsgExec msgs field @@ -63,10 +68,10 @@ func NewLegacyCosmosAnteHandlerEip712(ctx sdk.Context, options HandlerOptions, e authante.NewSetUpContextDecorator(), authante.NewValidateBasicDecorator(), authante.NewTxTimeoutHeightDecorator(), - NewMinGasPriceDecorator(options.FeeMarketKeeper, evmDenom), + NewMinGasPriceDecorator(options.FeeMarketKeeper, evmDenom, &feemarketParams), authante.NewValidateMemoDecorator(options.AccountKeeper), authante.NewConsumeGasForTxSizeDecorator(options.AccountKeeper), - NewDeductFeeDecorator(options.AccountKeeper, options.BankKeeper, options.FeegrantKeeper, options.TxFeeChecker), + NewDeductFeeDecorator(options.AccountKeeper, options.BankKeeper, options.FeegrantKeeper, txFeeChecker), // SetPubKeyDecorator must be called before all signature verification decorators authante.NewSetPubKeyDecorator(options.AccountKeeper), authante.NewValidateSigCountDecorator(options.AccountKeeper), @@ -75,7 +80,7 @@ func NewLegacyCosmosAnteHandlerEip712(ctx sdk.Context, options HandlerOptions, e NewLegacyEip712SigVerificationDecorator(options.AccountKeeper, options.SignModeHandler), authante.NewIncrementSequenceDecorator(options.AccountKeeper), ibcante.NewRedundantRelayDecorator(options.IBCKeeper), - NewGasWantedDecorator(options.FeeMarketKeeper, ethCfg), + NewGasWantedDecorator(options.FeeMarketKeeper, ethCfg, &feemarketParams), } decorators = append(decorators, extra...) return sdk.ChainAnteDecorators(decorators...) diff --git a/app/ante/fee_checker.go b/app/ante/fee_checker.go index f24249a31f..c3f169df2d 100644 --- a/app/ante/fee_checker.go +++ b/app/ante/fee_checker.go @@ -25,8 +25,10 @@ import ( sdk "github.com/cosmos/cosmos-sdk/types" errortypes "github.com/cosmos/cosmos-sdk/types/errors" authante "github.com/cosmos/cosmos-sdk/x/auth/ante" + "github.com/ethereum/go-ethereum/params" ethermint "github.com/evmos/ethermint/types" "github.com/evmos/ethermint/x/evm/types" + feemarkettypes "github.com/evmos/ethermint/x/feemarket/types" ) // NewDynamicFeeChecker returns a `TxFeeChecker` that applies a dynamic fee to @@ -37,7 +39,7 @@ import ( // - when `ExtensionOptionDynamicFeeTx` is omitted, `tipFeeCap` defaults to `MaxInt64`. // - when london hardfork is not enabled, it fallbacks to SDK default behavior (validator min-gas-prices). // - Tx priority is set to `effectiveGasPrice / DefaultPriorityReduction`. -func NewDynamicFeeChecker(k DynamicFeeEVMKeeper) authante.TxFeeChecker { +func NewDynamicFeeChecker(ethCfg *params.ChainConfig, evmParams *types.Params, feemarketParams *feemarkettypes.Params) authante.TxFeeChecker { return func(ctx sdk.Context, tx sdk.Tx) (sdk.Coins, int64, error) { feeTx, ok := tx.(sdk.FeeTx) if !ok { @@ -49,11 +51,9 @@ func NewDynamicFeeChecker(k DynamicFeeEVMKeeper) authante.TxFeeChecker { return checkTxFeeWithValidatorMinGasPrices(ctx, feeTx) } - params := k.GetParams(ctx) - denom := params.EvmDenom - ethCfg := params.ChainConfig.EthereumConfig(k.ChainID()) + denom := evmParams.EvmDenom - baseFee := k.GetBaseFee(ctx, ethCfg) + baseFee := types.GetBaseFee(ctx.BlockHeight(), ethCfg, feemarketParams) if baseFee == nil { // london hardfork is not enabled: fallback to min-gas-prices logic return checkTxFeeWithValidatorMinGasPrices(ctx, feeTx) diff --git a/app/ante/fee_checker_test.go b/app/ante/fee_checker_test.go index 9bb119dbe3..1b9d3ce851 100644 --- a/app/ante/fee_checker_test.go +++ b/app/ante/fee_checker_test.go @@ -17,10 +17,9 @@ import ( ethermint "github.com/evmos/ethermint/types" "github.com/evmos/ethermint/x/evm/types" evmtypes "github.com/evmos/ethermint/x/evm/types" + feemarkettypes "github.com/evmos/ethermint/x/feemarket/types" ) -var _ DynamicFeeEVMKeeper = MockEVMKeeper{} - type MockEVMKeeper struct { BaseFee *big.Int EnableLondonHF bool @@ -34,7 +33,11 @@ func (m MockEVMKeeper) GetBaseFee(ctx sdk.Context, ethCfg *params.ChainConfig) * } func (m MockEVMKeeper) GetParams(ctx sdk.Context) evmtypes.Params { - return evmtypes.DefaultParams() + params := evmtypes.DefaultParams() + if !m.EnableLondonHF { + params.ChainConfig.LondonBlock = nil + } + return params } func (m MockEVMKeeper) ChainID() *big.Int { @@ -61,7 +64,7 @@ func TestSDKTxFeeChecker(t *testing.T) { testCases := []struct { name string ctx sdk.Context - keeper DynamicFeeEVMKeeper + keeper MockEVMKeeper buildTx func() sdk.Tx expFees string expPriority int64 @@ -207,7 +210,15 @@ func TestSDKTxFeeChecker(t *testing.T) { for _, tc := range testCases { t.Run(tc.name, func(t *testing.T) { - fees, priority, err := NewDynamicFeeChecker(tc.keeper)(tc.ctx, tc.buildTx()) + evmParams := tc.keeper.GetParams(tc.ctx) + feemarketParams := feemarkettypes.Params{ + NoBaseFee: false, + BaseFee: sdk.NewIntFromBigInt(tc.keeper.BaseFee), + } + chainID := tc.keeper.ChainID() + chainCfg := evmParams.GetChainConfig() + ethCfg := chainCfg.EthereumConfig(chainID) + fees, priority, err := NewDynamicFeeChecker(ethCfg, &evmParams, &feemarketParams)(tc.ctx, tc.buildTx()) if tc.expSuccess { require.Equal(t, tc.expFees, fees.String()) require.Equal(t, tc.expPriority, priority) diff --git a/app/ante/fee_market.go b/app/ante/fee_market.go index 6ee8d4adea..4025f71fda 100644 --- a/app/ante/fee_market.go +++ b/app/ante/fee_market.go @@ -21,6 +21,7 @@ import ( errorsmod "cosmossdk.io/errors" sdk "github.com/cosmos/cosmos-sdk/types" "github.com/ethereum/go-ethereum/params" + feemarkettypes "github.com/evmos/ethermint/x/feemarket/types" ) // GasWantedDecorator keeps track of the gasWanted amount on the current block in transient store @@ -29,16 +30,19 @@ import ( type GasWantedDecorator struct { feeMarketKeeper FeeMarketKeeper ethCfg *params.ChainConfig + feemarketParams *feemarkettypes.Params } // NewGasWantedDecorator creates a new NewGasWantedDecorator func NewGasWantedDecorator( feeMarketKeeper FeeMarketKeeper, ethCfg *params.ChainConfig, + feemarketParams *feemarkettypes.Params, ) GasWantedDecorator { return GasWantedDecorator{ feeMarketKeeper, ethCfg, + feemarketParams, } } @@ -52,7 +56,7 @@ func (gwd GasWantedDecorator) AnteHandle(ctx sdk.Context, tx sdk.Tx, simulate bo } gasWanted := feeTx.GetGas() - isBaseFeeEnabled := gwd.feeMarketKeeper.GetBaseFeeEnabled(ctx) + isBaseFeeEnabled := gwd.feemarketParams.IsBaseFeeEnabled(ctx.BlockHeight()) // Add total gasWanted to cumulative in block transientStore in FeeMarket module if isBaseFeeEnabled { diff --git a/app/ante/fee_market_test.go b/app/ante/fee_market_test.go index 8554e665ea..fd2570439d 100644 --- a/app/ante/fee_market_test.go +++ b/app/ante/fee_market_test.go @@ -17,11 +17,12 @@ func (suite *AnteTestSuite) TestGasWantedDecorator() { suite.SetupTest() evmParams := suite.app.EvmKeeper.GetParams(suite.ctx) + feemarketParams := suite.app.FeeMarketKeeper.GetParams(suite.ctx) chainID := suite.app.EvmKeeper.ChainID() chainCfg := evmParams.GetChainConfig() ethCfg := chainCfg.EthereumConfig(chainID) - dec := ante.NewGasWantedDecorator(suite.app.FeeMarketKeeper, ethCfg) + dec := ante.NewGasWantedDecorator(suite.app.FeeMarketKeeper, ethCfg, &feemarketParams) from, fromPrivKey := tests.NewAddrKey() to := tests.GenerateAddress() diff --git a/app/ante/fees.go b/app/ante/fees.go index c780a935c6..92e1049982 100644 --- a/app/ante/fees.go +++ b/app/ante/fees.go @@ -24,6 +24,7 @@ import ( ethtypes "github.com/ethereum/go-ethereum/core/types" evmtypes "github.com/evmos/ethermint/x/evm/types" + feemarkettypes "github.com/evmos/ethermint/x/feemarket/types" ) // MinGasPriceDecorator will check if the transaction's fee is at least as large @@ -32,8 +33,9 @@ import ( // If fee is high enough, then call next AnteHandler // CONTRACT: Tx must implement FeeTx to use MinGasPriceDecorator type MinGasPriceDecorator struct { - feesKeeper FeeMarketKeeper - evmDenom string + feesKeeper FeeMarketKeeper + evmDenom string + feemarketParams *feemarkettypes.Params } // EthMinGasPriceDecorator will check if the transaction's fee is at least as large @@ -42,8 +44,9 @@ type MinGasPriceDecorator struct { // if London hard fork or fee market params (EIP-1559) are enabled. // If fee is high enough, then call next AnteHandler type EthMinGasPriceDecorator struct { - feesKeeper FeeMarketKeeper - baseFee *big.Int + feesKeeper FeeMarketKeeper + baseFee *big.Int + feemarketParams *feemarkettypes.Params } // EthMempoolFeeDecorator will check if the transaction's effective fee is at least as large @@ -59,14 +62,14 @@ type EthMempoolFeeDecorator struct { // NewMinGasPriceDecorator creates a new MinGasPriceDecorator instance used only for // Cosmos transactions. -func NewMinGasPriceDecorator(fk FeeMarketKeeper, evmDenom string) MinGasPriceDecorator { - return MinGasPriceDecorator{feesKeeper: fk, evmDenom: evmDenom} +func NewMinGasPriceDecorator(fk FeeMarketKeeper, evmDenom string, feemarketParams *feemarkettypes.Params) MinGasPriceDecorator { + return MinGasPriceDecorator{feesKeeper: fk, evmDenom: evmDenom, feemarketParams: feemarketParams} } // NewEthMinGasPriceDecorator creates a new MinGasPriceDecorator instance used only for // Ethereum transactions. -func NewEthMinGasPriceDecorator(fk FeeMarketKeeper, baseFee *big.Int) EthMinGasPriceDecorator { - return EthMinGasPriceDecorator{feesKeeper: fk, baseFee: baseFee} +func NewEthMinGasPriceDecorator(fk FeeMarketKeeper, baseFee *big.Int, feemarketParams *feemarkettypes.Params) EthMinGasPriceDecorator { + return EthMinGasPriceDecorator{feesKeeper: fk, baseFee: baseFee, feemarketParams: feemarketParams} } // NewEthMempoolFeeDecorator creates a new NewEthMempoolFeeDecorator instance used only for @@ -84,7 +87,7 @@ func (mpd MinGasPriceDecorator) AnteHandle(ctx sdk.Context, tx sdk.Tx, simulate return ctx, errorsmod.Wrapf(errortypes.ErrInvalidType, "invalid transaction type %T, expected sdk.FeeTx", tx) } - minGasPrice := mpd.feesKeeper.GetParams(ctx).MinGasPrice + minGasPrice := mpd.feemarketParams.MinGasPrice // Short-circuit if min gas price is 0 or if simulating if minGasPrice.IsZero() || simulate { @@ -126,7 +129,7 @@ func (mpd MinGasPriceDecorator) AnteHandle(ctx sdk.Context, tx sdk.Tx, simulate // AnteHandle ensures that the that the effective fee from the transaction is greater than the // minimum global fee, which is defined by the MinGasPrice (parameter) * GasLimit (tx argument). func (empd EthMinGasPriceDecorator) AnteHandle(ctx sdk.Context, tx sdk.Tx, simulate bool, next sdk.AnteHandler) (newCtx sdk.Context, err error) { - minGasPrice := empd.feesKeeper.GetParams(ctx).MinGasPrice + minGasPrice := empd.feemarketParams.MinGasPrice // short-circuit if min gas price is 0 if minGasPrice.IsZero() { diff --git a/app/ante/fees_test.go b/app/ante/fees_test.go index c505dd866b..711e13eaf4 100644 --- a/app/ante/fees_test.go +++ b/app/ante/fees_test.go @@ -122,7 +122,8 @@ func (s *AnteTestSuite) TestMinGasPriceDecorator() { s.Run(et.name+"_"+tc.name, func() { // s.SetupTest(et.isCheckTx) ctx := s.ctx.WithIsReCheckTx(et.isCheckTx) - dec := ante.NewMinGasPriceDecorator(s.app.FeeMarketKeeper, evmtypes.DefaultEVMDenom) + feemarketParams := s.app.FeeMarketKeeper.GetParams(ctx) + dec := ante.NewMinGasPriceDecorator(s.app.FeeMarketKeeper, evmtypes.DefaultEVMDenom, &feemarketParams) _, err := dec.AnteHandle(ctx, tc.malleate(), et.simulate, NextFn) if tc.expPass || (et.simulate && tc.allowPassOnSimulate) { @@ -339,8 +340,9 @@ func (s *AnteTestSuite) TestEthMinGasPriceDecorator() { chainCfg := evmParams.GetChainConfig() ethCfg := chainCfg.EthereumConfig(chainID) baseFee := s.app.EvmKeeper.GetBaseFee(s.ctx, ethCfg) + feemarketParams := s.app.FeeMarketKeeper.GetParams(s.ctx) - dec := ante.NewEthMinGasPriceDecorator(s.app.FeeMarketKeeper, baseFee) + dec := ante.NewEthMinGasPriceDecorator(s.app.FeeMarketKeeper, baseFee, &feemarketParams) _, err := dec.AnteHandle(s.ctx, tx, et.simulate, NextFn) if tc.expPass { diff --git a/app/ante/handler_options.go b/app/ante/handler_options.go index 5879fc7fc8..ff81cc9daa 100644 --- a/app/ante/handler_options.go +++ b/app/ante/handler_options.go @@ -43,9 +43,10 @@ type HandlerOptions struct { SigGasConsumer func(meter sdk.GasMeter, sig signing.SignatureV2, params authtypes.Params) error MaxTxGasWanted uint64 ExtensionOptionChecker ante.ExtensionOptionChecker - TxFeeChecker ante.TxFeeChecker - DisabledAuthzMsgs []string - ExtraDecorators []sdk.AnteDecorator + // use dynamic fee checker or the cosmos-sdk default one for native transactions + DynamicFeeChecker bool + DisabledAuthzMsgs []string + ExtraDecorators []sdk.AnteDecorator } func (options HandlerOptions) validate() error { @@ -69,22 +70,23 @@ func (options HandlerOptions) validate() error { func newEthAnteHandler(ctx sdk.Context, options HandlerOptions, extra ...sdk.AnteDecorator) sdk.AnteHandler { evmParams := options.EvmKeeper.GetParams(ctx) + feemarketParams := options.FeeMarketKeeper.GetParams(ctx) evmDenom := evmParams.EvmDenom chainID := options.EvmKeeper.ChainID() chainCfg := evmParams.GetChainConfig() ethCfg := chainCfg.EthereumConfig(chainID) - baseFee := options.EvmKeeper.GetBaseFee(ctx, ethCfg) + baseFee := evmtypes.GetBaseFee(ctx.BlockHeight(), ethCfg, &feemarketParams) decorators := []sdk.AnteDecorator{ - NewEthSetUpContextDecorator(options.EvmKeeper), // outermost AnteDecorator. SetUpContext must be called first - NewEthMempoolFeeDecorator(evmDenom, baseFee), // Check eth effective gas price against minimal-gas-prices - NewEthMinGasPriceDecorator(options.FeeMarketKeeper, baseFee), // Check eth effective gas price against the global MinGasPrice + NewEthSetUpContextDecorator(options.EvmKeeper), // outermost AnteDecorator. SetUpContext must be called first + NewEthMempoolFeeDecorator(evmDenom, baseFee), // Check eth effective gas price against minimal-gas-prices + NewEthMinGasPriceDecorator(options.FeeMarketKeeper, baseFee, &feemarketParams), // Check eth effective gas price against the global MinGasPrice NewEthValidateBasicDecorator(&evmParams, baseFee), NewEthSigVerificationDecorator(chainID), NewEthAccountVerificationDecorator(options.AccountKeeper, options.EvmKeeper, evmDenom), NewCanTransferDecorator(options.EvmKeeper, baseFee, &evmParams, ethCfg), NewEthGasConsumeDecorator(options.EvmKeeper, options.MaxTxGasWanted, ethCfg, evmDenom, baseFee), NewEthIncrementSenderSequenceDecorator(options.AccountKeeper), // innermost AnteDecorator. - NewGasWantedDecorator(options.FeeMarketKeeper, ethCfg), + NewGasWantedDecorator(options.FeeMarketKeeper, ethCfg, &feemarketParams), NewEthEmitEventDecorator(options.EvmKeeper), // emit eth tx hash and index at the very last ante handler. } decorators = append(decorators, extra...) @@ -93,10 +95,15 @@ func newEthAnteHandler(ctx sdk.Context, options HandlerOptions, extra ...sdk.Ant func newCosmosAnteHandler(ctx sdk.Context, options HandlerOptions, extra ...sdk.AnteDecorator) sdk.AnteHandler { evmParams := options.EvmKeeper.GetParams(ctx) + feemarketParams := options.FeeMarketKeeper.GetParams(ctx) evmDenom := evmParams.EvmDenom chainID := options.EvmKeeper.ChainID() chainCfg := evmParams.GetChainConfig() ethCfg := chainCfg.EthereumConfig(chainID) + var txFeeChecker ante.TxFeeChecker + if options.DynamicFeeChecker { + txFeeChecker = NewDynamicFeeChecker(ethCfg, &evmParams, &feemarketParams) + } decorators := []sdk.AnteDecorator{ RejectMessagesDecorator{}, // reject MsgEthereumTxs // disable the Msg types that cannot be included on an authz.MsgExec msgs field @@ -105,10 +112,10 @@ func newCosmosAnteHandler(ctx sdk.Context, options HandlerOptions, extra ...sdk. ante.NewExtensionOptionsDecorator(options.ExtensionOptionChecker), ante.NewValidateBasicDecorator(), ante.NewTxTimeoutHeightDecorator(), - NewMinGasPriceDecorator(options.FeeMarketKeeper, evmDenom), + NewMinGasPriceDecorator(options.FeeMarketKeeper, evmDenom, &feemarketParams), ante.NewValidateMemoDecorator(options.AccountKeeper), ante.NewConsumeGasForTxSizeDecorator(options.AccountKeeper), - NewDeductFeeDecorator(options.AccountKeeper, options.BankKeeper, options.FeegrantKeeper, options.TxFeeChecker), + NewDeductFeeDecorator(options.AccountKeeper, options.BankKeeper, options.FeegrantKeeper, txFeeChecker), // SetPubKeyDecorator must be called before all signature verification decorators ante.NewSetPubKeyDecorator(options.AccountKeeper), ante.NewValidateSigCountDecorator(options.AccountKeeper), @@ -116,7 +123,7 @@ func newCosmosAnteHandler(ctx sdk.Context, options HandlerOptions, extra ...sdk. ante.NewSigVerificationDecorator(options.AccountKeeper, options.SignModeHandler), ante.NewIncrementSequenceDecorator(options.AccountKeeper), ibcante.NewRedundantRelayDecorator(options.IBCKeeper), - NewGasWantedDecorator(options.FeeMarketKeeper, ethCfg), + NewGasWantedDecorator(options.FeeMarketKeeper, ethCfg, &feemarketParams), } decorators = append(decorators, extra...) return sdk.ChainAnteDecorators(decorators...) diff --git a/app/ante/interfaces.go b/app/ante/interfaces.go index dc0c73cffa..b728233f13 100644 --- a/app/ante/interfaces.go +++ b/app/ante/interfaces.go @@ -22,23 +22,14 @@ import ( tx "github.com/cosmos/cosmos-sdk/types/tx" "github.com/ethereum/go-ethereum/common" - "github.com/ethereum/go-ethereum/params" "github.com/evmos/ethermint/x/evm/statedb" - evmtypes "github.com/evmos/ethermint/x/evm/types" feemarkettypes "github.com/evmos/ethermint/x/feemarket/types" ) -// DynamicFeeEVMKeeper is a subset of EVMKeeper interface that supports dynamic fee checker -type DynamicFeeEVMKeeper interface { - ChainID() *big.Int - GetParams(ctx sdk.Context) evmtypes.Params - GetBaseFee(ctx sdk.Context, ethCfg *params.ChainConfig) *big.Int -} - // EVMKeeper defines the expected keeper interface used on the Eth AnteHandler type EVMKeeper interface { statedb.Keeper - DynamicFeeEVMKeeper + ChainID() *big.Int DeductTxCostsFromUserBalance(ctx sdk.Context, fees sdk.Coins, from common.Address) error ResetTransientGasUsed(ctx sdk.Context) @@ -53,5 +44,4 @@ type protoTxProvider interface { type FeeMarketKeeper interface { GetParams(ctx sdk.Context) (params feemarkettypes.Params) AddTransientGasWanted(ctx sdk.Context, gasWanted uint64) (uint64, error) - GetBaseFeeEnabled(ctx sdk.Context) bool } diff --git a/app/ante/sigs_test.go b/app/ante/sigs_test.go index 83a5aa6ea7..8b0deab64c 100644 --- a/app/ante/sigs_test.go +++ b/app/ante/sigs_test.go @@ -20,7 +20,7 @@ func (suite *AnteTestSuite) TestSignatures() { balance := big.NewInt(10000000000) suite.app.EvmKeeper.SetAccount(suite.ctx, addr, *acc) - suite.app.EvmKeeper.SetBalance(suite.ctx, addr, balance) + suite.app.EvmKeeper.SetBalance(suite.ctx, addr, balance, evmtypes.DefaultEVMDenom) msgEthereumTx := evmtypes.NewTx(suite.app.EvmKeeper.ChainID(), 1, &to, big.NewInt(10), 100000, big.NewInt(1), nil, nil, nil, nil) msgEthereumTx.From = addr.Bytes() diff --git a/app/ante/utils_test.go b/app/ante/utils_test.go index 09cc50f053..8972f50dc1 100644 --- a/app/ante/utils_test.go +++ b/app/ante/utils_test.go @@ -552,7 +552,7 @@ func (suite *AnteTestSuite) RegisterAccount(pubKey cryptotypes.PubKey, balance * acc := suite.app.AccountKeeper.NewAccountWithAddress(suite.ctx, sdk.AccAddress(pubKey.Address())) suite.app.AccountKeeper.SetAccount(suite.ctx, acc) - suite.app.EvmKeeper.SetBalance(suite.ctx, common.BytesToAddress(pubKey.Address()), balance) + suite.app.EvmKeeper.SetBalance(suite.ctx, common.BytesToAddress(pubKey.Address()), balance, evmtypes.DefaultEVMDenom) } // createSignerBytes generates sign doc bytes using the given parameters diff --git a/app/app.go b/app/app.go index 3d0bf0def3..87f97a1ebd 100644 --- a/app/app.go +++ b/app/app.go @@ -761,7 +761,7 @@ func (app *EthermintApp) setAnteHandler(txConfig client.TxConfig, maxGasWanted u FeeMarketKeeper: app.FeeMarketKeeper, MaxTxGasWanted: maxGasWanted, ExtensionOptionChecker: ethermint.HasDynamicFeeExtensionOption, - TxFeeChecker: ante.NewDynamicFeeChecker(app.EvmKeeper), + DynamicFeeChecker: true, DisabledAuthzMsgs: []string{ sdk.MsgTypeURL(&evmtypes.MsgEthereumTx{}), sdk.MsgTypeURL(&vestingtypes.MsgCreateVestingAccount{}), diff --git a/x/evm/handler_test.go b/x/evm/handler_test.go index 1e9da1b20d..760867a783 100644 --- a/x/evm/handler_test.go +++ b/x/evm/handler_test.go @@ -467,7 +467,7 @@ func (suite *HandlerTestSuite) TestERC20TransferReverted() { k.SetHooks(tc.hooks) // add some fund to pay gas fee - k.SetBalance(suite.Ctx, suite.Address, big.NewInt(1000000000000000)) + k.SetBalance(suite.Ctx, suite.Address, big.NewInt(1000000000000000), types.DefaultEVMDenom) contract := suite.deployERC20Contract() diff --git a/x/evm/keeper/config.go b/x/evm/keeper/config.go index 068501fce5..928c742f4a 100644 --- a/x/evm/keeper/config.go +++ b/x/evm/keeper/config.go @@ -27,20 +27,22 @@ import ( rpctypes "github.com/evmos/ethermint/rpc/types" "github.com/evmos/ethermint/x/evm/statedb" "github.com/evmos/ethermint/x/evm/types" + feemarkettypes "github.com/evmos/ethermint/x/feemarket/types" ) // EVMConfig encapsulates common parameters needed to create an EVM to execute a message // It's mainly to reduce the number of method parameters type EVMConfig struct { - Params types.Params - ChainConfig *params.ChainConfig - CoinBase common.Address - BaseFee *big.Int - TxConfig statedb.TxConfig - Tracer vm.EVMLogger - DebugTrace bool - Overrides *rpctypes.StateOverride - BlockOverrides *rpctypes.BlockOverrides + Params types.Params + FeeMarketParams feemarkettypes.Params + ChainConfig *params.ChainConfig + CoinBase common.Address + BaseFee *big.Int + TxConfig statedb.TxConfig + Tracer vm.EVMLogger + DebugTrace bool + Overrides *rpctypes.StateOverride + BlockOverrides *rpctypes.BlockOverrides } // EVMConfig creates the EVMConfig based on current state @@ -48,6 +50,8 @@ func (k *Keeper) EVMConfig(ctx sdk.Context, proposerAddress sdk.ConsAddress, cha params := k.GetParams(ctx) ethCfg := params.ChainConfig.EthereumConfig(chainID) + feemarketParams := k.feeMarketKeeper.GetParams(ctx) + // get the coinbase address from the block proposer coinbase, err := k.GetCoinbaseAddress(ctx, proposerAddress) if err != nil { @@ -61,13 +65,22 @@ func (k *Keeper) EVMConfig(ctx sdk.Context, proposerAddress sdk.ConsAddress, cha txConfig = k.TxConfig(ctx, txHash) } - baseFee := k.GetBaseFee(ctx, ethCfg) + var baseFee *big.Int + if types.IsLondon(ethCfg, ctx.BlockHeight()) { + baseFee = feemarketParams.GetBaseFee() + // should not be nil if london hardfork enabled + if baseFee == nil { + baseFee = new(big.Int) + } + } + return &EVMConfig{ - Params: params, - ChainConfig: ethCfg, - CoinBase: coinbase, - BaseFee: baseFee, - TxConfig: txConfig, + Params: params, + FeeMarketParams: feemarketParams, + ChainConfig: ethCfg, + CoinBase: coinbase, + BaseFee: baseFee, + TxConfig: txConfig, }, nil } @@ -86,7 +99,7 @@ func (k *Keeper) TxConfig(ctx sdk.Context, txHash common.Hash) statedb.TxConfig func (k Keeper) VMConfig(ctx sdk.Context, _ core.Message, cfg *EVMConfig) vm.Config { noBaseFee := true if types.IsLondon(cfg.ChainConfig, ctx.BlockHeight()) { - noBaseFee = k.feeMarketKeeper.GetParams(ctx).NoBaseFee + noBaseFee = cfg.FeeMarketParams.NoBaseFee } if _, ok := cfg.Tracer.(*types.NoOpTracer); ok { diff --git a/x/evm/keeper/grpc_query_test.go b/x/evm/keeper/grpc_query_test.go index 461f3e9b48..118765b85a 100644 --- a/x/evm/keeper/grpc_query_test.go +++ b/x/evm/keeper/grpc_query_test.go @@ -1222,7 +1222,7 @@ func (suite *GRPCServerTestSuiteSuite) TestTraceBlock() { // Deploy contract contractAddr := suite.deployTestContract(suite.Address) // set some balance to handle fees - suite.App.EvmKeeper.SetBalance(suite.Ctx, suite.Address, big.NewInt(1000000000000000000)) + suite.App.EvmKeeper.SetBalance(suite.Ctx, suite.Address, big.NewInt(1000000000000000000), types.DefaultEVMDenom) suite.Commit() // Generate token transfer transaction txMsg := suite.transferERC20Token(suite.T(), contractAddr, suite.Address, common.HexToAddress("0x378c50D9264C63F3F92B806d4ee56E9D86FfB3Ec"), sdkmath.NewIntWithDecimal(1, 18).BigInt()) diff --git a/x/evm/keeper/keeper.go b/x/evm/keeper/keeper.go index a691bf4422..98168c6ad4 100644 --- a/x/evm/keeper/keeper.go +++ b/x/evm/keeper/keeper.go @@ -359,16 +359,6 @@ func (k Keeper) getBaseFee(ctx sdk.Context, london bool) *big.Int { return baseFee } -// GetMinGasMultiplier returns the MinGasMultiplier param from the fee market module -func (k Keeper) GetMinGasMultiplier(ctx sdk.Context) sdk.Dec { - fmkParmas := k.feeMarketKeeper.GetParams(ctx) - if fmkParmas.MinGasMultiplier.IsNil() { - // in case we are executing eth_call on a legacy block, returns a zero value. - return sdk.ZeroDec() - } - return fmkParmas.MinGasMultiplier -} - // ResetTransientGasUsed reset gas used to prepare for execution of current cosmos tx, called in ante handler. func (k Keeper) ResetTransientGasUsed(ctx sdk.Context) { store := ctx.TransientStore(k.transientKey) diff --git a/x/evm/keeper/state_transition.go b/x/evm/keeper/state_transition.go index 839b6d7d3f..15a9537a5c 100644 --- a/x/evm/keeper/state_transition.go +++ b/x/evm/keeper/state_transition.go @@ -354,7 +354,7 @@ func (k *Keeper) ApplyMessageWithConfig( return nil, errorsmod.Wrap(types.ErrCallDisabled, "failed to call contract") } - stateDB := statedb.NewWithParams(ctx, k, cfg.TxConfig, cfg.Params) + stateDB := statedb.NewWithParams(ctx, k, cfg.TxConfig, cfg.Params.EvmDenom) var evm *vm.EVM if cfg.Overrides != nil { if err := cfg.Overrides.Apply(stateDB); err != nil { @@ -453,7 +453,11 @@ func (k *Keeper) ApplyMessageWithConfig( // is considerably higher than GasUsed to stay more aligned with Tendermint gas mechanics // for more info https://github.com/evmos/ethermint/issues/1085 gasLimit := sdk.NewDec(int64(msg.GasLimit)) - minGasMultiplier := k.GetMinGasMultiplier(ctx) + minGasMultiplier := cfg.FeeMarketParams.MinGasMultiplier + if minGasMultiplier.IsNil() { + // in case we are executing eth_call on a legacy block, returns a zero value. + minGasMultiplier = sdk.ZeroDec() + } minimumGasUsed := gasLimit.Mul(minGasMultiplier) if msg.GasLimit < leftoverGas { diff --git a/x/evm/keeper/statedb.go b/x/evm/keeper/statedb.go index d414bd193d..575b723a08 100644 --- a/x/evm/keeper/statedb.go +++ b/x/evm/keeper/statedb.go @@ -85,8 +85,7 @@ func (k *Keeper) SubBalance(ctx sdk.Context, addr sdk.AccAddress, coins sdk.Coin } // SetBalance reset the account's balance, mainly used by unit tests -func (k *Keeper) SetBalance(ctx sdk.Context, addr common.Address, amount *big.Int) error { - evmDenom := k.GetParams(ctx).EvmDenom +func (k *Keeper) SetBalance(ctx sdk.Context, addr common.Address, amount *big.Int, evmDenom string) error { cosmosAddr := sdk.AccAddress(addr.Bytes()) balance := k.GetBalance(ctx, cosmosAddr, evmDenom) delta := new(big.Int).Sub(amount, balance) diff --git a/x/evm/keeper/statedb_test.go b/x/evm/keeper/statedb_test.go index 4312de6443..098d8123ba 100644 --- a/x/evm/keeper/statedb_test.go +++ b/x/evm/keeper/statedb_test.go @@ -862,7 +862,7 @@ func (suite *StateDBTestSuite) TestSetBalance() { suite.Run(tc.name, func() { suite.SetupTest() tc.malleate() - err := suite.App.EvmKeeper.SetBalance(suite.Ctx, tc.addr, amount) + err := suite.App.EvmKeeper.SetBalance(suite.Ctx, tc.addr, amount, types.DefaultEVMDenom) if tc.expErr { suite.Require().Error(err) } else { diff --git a/x/evm/statedb/interfaces.go b/x/evm/statedb/interfaces.go index d6fa79b2cf..ae7e1fd250 100644 --- a/x/evm/statedb/interfaces.go +++ b/x/evm/statedb/interfaces.go @@ -32,7 +32,7 @@ type Keeper interface { AddBalance(ctx sdk.Context, addr sdk.AccAddress, coins sdk.Coins) error SubBalance(ctx sdk.Context, addr sdk.AccAddress, coins sdk.Coins) error - SetBalance(ctx sdk.Context, addr common.Address, amount *big.Int) error + SetBalance(ctx sdk.Context, addr common.Address, amount *big.Int, denom string) error GetBalance(ctx sdk.Context, addr sdk.AccAddress, denom string) *big.Int // Read methods diff --git a/x/evm/statedb/statedb.go b/x/evm/statedb/statedb.go index f210523b4f..5ace8b3a40 100644 --- a/x/evm/statedb/statedb.go +++ b/x/evm/statedb/statedb.go @@ -27,7 +27,6 @@ import ( "github.com/ethereum/go-ethereum/core/vm" "github.com/ethereum/go-ethereum/crypto" "github.com/ethereum/go-ethereum/params" - evmtypes "github.com/evmos/ethermint/x/evm/types" "github.com/evmos/ethermint/store/cachemulti" ) @@ -88,10 +87,10 @@ type StateDB struct { // New creates a new state from a given trie. func New(ctx sdk.Context, keeper Keeper, txConfig TxConfig) *StateDB { - return NewWithParams(ctx, keeper, txConfig, keeper.GetParams(ctx)) + return NewWithParams(ctx, keeper, txConfig, keeper.GetParams(ctx).EvmDenom) } -func NewWithParams(ctx sdk.Context, keeper Keeper, txConfig TxConfig, params evmtypes.Params) *StateDB { +func NewWithParams(ctx sdk.Context, keeper Keeper, txConfig TxConfig, evmDenom string) *StateDB { db := &StateDB{ keeper: keeper, stateObjects: make(map[common.Address]*stateObject), @@ -101,7 +100,7 @@ func NewWithParams(ctx sdk.Context, keeper Keeper, txConfig TxConfig, params evm txConfig: txConfig, nativeEvents: sdk.Events{}, - evmDenom: params.EvmDenom, + evmDenom: evmDenom, } db.ctx = ctx.WithValue(StateDBContextKey, db) db.cacheCtx = db.ctx.WithMultiStore(cachemulti.NewStore(ctx.MultiStore(), keeper.StoreKeys())) @@ -393,7 +392,7 @@ func (s *StateDB) SubBalance(addr common.Address, amount *big.Int) { func (s *StateDB) SetBalance(addr common.Address, amount *big.Int) { if err := s.ExecuteNativeAction(common.Address{}, nil, func(ctx sdk.Context) error { - return s.keeper.SetBalance(ctx, addr, amount) + return s.keeper.SetBalance(ctx, addr, amount, s.evmDenom) }); err != nil { s.err = err } diff --git a/x/evm/types/utils.go b/x/evm/types/utils.go index 3b74fdcda6..145077146c 100644 --- a/x/evm/types/utils.go +++ b/x/evm/types/utils.go @@ -21,6 +21,7 @@ import ( "math/big" "github.com/cosmos/gogoproto/proto" + feemarkettypes "github.com/evmos/ethermint/x/feemarket/types" errorsmod "cosmossdk.io/errors" sdk "github.com/cosmos/cosmos-sdk/types" @@ -29,6 +30,7 @@ import ( "github.com/ethereum/go-ethereum/common/math" ethtypes "github.com/ethereum/go-ethereum/core/types" "github.com/ethereum/go-ethereum/crypto" + "github.com/ethereum/go-ethereum/params" ) // DefaultPriorityReduction is the default amount of price values required for 1 unit of priority. @@ -190,3 +192,15 @@ func HexAddress(a []byte) string { hex.Encode(buf[2:], a) return string(buf[:]) } + +func GetBaseFee(height int64, ethCfg *params.ChainConfig, feemarketParams *feemarkettypes.Params) *big.Int { + if !IsLondon(ethCfg, height) { + return nil + } + baseFee := feemarketParams.GetBaseFee() + // should not be nil if london hardfork enabled + if baseFee == nil { + return new(big.Int) + } + return baseFee +} diff --git a/x/feemarket/keeper/params.go b/x/feemarket/keeper/params.go index f8a1f3744f..3e11a48c83 100644 --- a/x/feemarket/keeper/params.go +++ b/x/feemarket/keeper/params.go @@ -55,12 +55,6 @@ func (k Keeper) SetParams(ctx sdk.Context, params types.Params) error { // Required by EIP1559 base fee calculation. // ---------------------------------------------------------------------------- -// GetBaseFeeEnabled returns true if base fee is enabled -func (k Keeper) GetBaseFeeEnabled(ctx sdk.Context) bool { - params := k.GetParams(ctx) - return !params.NoBaseFee && ctx.BlockHeight() >= params.EnableHeight -} - // GetBaseFee gets the base fee from the store func (k Keeper) GetBaseFee(ctx sdk.Context) *big.Int { params := k.GetParams(ctx) diff --git a/x/feemarket/keeper/params_test.go b/x/feemarket/keeper/params_test.go index 9533478d0a..b3a44eccad 100644 --- a/x/feemarket/keeper/params_test.go +++ b/x/feemarket/keeper/params_test.go @@ -55,7 +55,7 @@ func (suite *ParamsTestSuite) TestSetGetParams() { return true }, func() interface{} { - return suite.App.FeeMarketKeeper.GetBaseFeeEnabled(suite.Ctx) + return suite.App.FeeMarketKeeper.GetParams(suite.Ctx).IsBaseFeeEnabled(suite.Ctx.BlockHeight()) }, true, }, @@ -68,7 +68,7 @@ func (suite *ParamsTestSuite) TestSetGetParams() { return true }, func() interface{} { - return suite.App.FeeMarketKeeper.GetBaseFeeEnabled(suite.Ctx) + return suite.App.FeeMarketKeeper.GetParams(suite.Ctx).IsBaseFeeEnabled(suite.Ctx.BlockHeight()) }, false, }, diff --git a/x/feemarket/types/params.go b/x/feemarket/types/params.go index f8a5c65a9d..f2511c38bc 100644 --- a/x/feemarket/types/params.go +++ b/x/feemarket/types/params.go @@ -17,6 +17,7 @@ package types import ( "fmt" + "math/big" sdkmath "cosmossdk.io/math" sdk "github.com/cosmos/cosmos-sdk/types" @@ -128,10 +129,18 @@ func validateBool(i interface{}) error { return nil } -func (p *Params) IsBaseFeeEnabled(height int64) bool { +func (p Params) IsBaseFeeEnabled(height int64) bool { return !p.NoBaseFee && height >= p.EnableHeight } +func (p Params) GetBaseFee() *big.Int { + if p.NoBaseFee { + return nil + } + + return p.BaseFee.BigInt() +} + func validateMinGasPrice(i interface{}) error { v, ok := i.(sdk.Dec)