diff --git a/app/evmante_fee_checker.go b/app/evmante_fee_checker.go index 5299e0eb1..5bc5c50f2 100644 --- a/app/evmante_fee_checker.go +++ b/app/evmante_fee_checker.go @@ -26,7 +26,9 @@ import ( // - Tx priority is set to `effectiveGasPrice / DefaultPriorityReduction`. func NewDynamicFeeChecker(k evmkeeper.Keeper) ante.TxFeeChecker { return func(ctx sdk.Context, feeTx sdk.FeeTx) (sdk.Coins, int64, error) { - // TODO: in the e2e test, if the fee in the genesis transaction meet the baseFee and minGasPrice in the feemarket, we can remove this code + // TODO: in the e2e test, + // if the fee in the genesis transaction meet the baseFee and minGasPrice in the feemarket, + // we can remove this code if ctx.BlockHeight() == 0 { // genesis transactions: fallback to min-gas-price logic return checkTxFeeWithValidatorMinGasPrices(ctx, feeTx) @@ -51,7 +53,10 @@ func NewDynamicFeeChecker(k evmkeeper.Keeper) ante.TxFeeChecker { // priority fee cannot be negative if maxPriorityPrice.IsNegative() { - return nil, 0, errors.Wrapf(errortypes.ErrInsufficientFee, "max priority price cannot be negative") + return nil, 0, errors.Wrapf( + errortypes.ErrInsufficientFee, + "max priority price cannot be negative", + ) } gas := feeTx.GetGas() @@ -62,11 +67,21 @@ func NewDynamicFeeChecker(k evmkeeper.Keeper) ante.TxFeeChecker { baseFeeInt := sdkmath.NewIntFromBigInt(baseFee) if feeCap.LT(baseFeeInt) { - return nil, 0, errors.Wrapf(errortypes.ErrInsufficientFee, "gas prices too low, got: %s%s required: %s%s. Please retry using a higher gas price or a higher fee", feeCap, denom, baseFeeInt, denom) + return nil, 0, errors.Wrapf( + errortypes.ErrInsufficientFee, + "gas prices too low, got: %s%s required: %s%s. "+ + "Please retry using a higher gas price or a higher fee", + feeCap, + denom, + baseFeeInt, + denom, + ) } // calculate the effective gas price using the EIP-1559 logic. - effectivePrice := sdkmath.NewIntFromBigInt(evm.EffectiveGasPrice(baseFeeInt.BigInt(), feeCap.BigInt(), maxPriorityPrice.BigInt())) + effectivePrice := sdkmath.NewIntFromBigInt( + evm.EffectiveGasPrice(baseFeeInt.BigInt(), feeCap.BigInt(), maxPriorityPrice.BigInt()), + ) // NOTE: create a new coins slice without having to validate the denom effectiveFee := sdk.Coins{ @@ -109,7 +124,10 @@ func checkTxFeeWithValidatorMinGasPrices(ctx sdk.Context, tx sdk.FeeTx) (sdk.Coi } if !feeCoins.IsAnyGTE(requiredFees) { - return nil, 0, errors.Wrapf(errortypes.ErrInsufficientFee, "insufficient fees; got: %s required: %s", feeCoins, requiredFees) + return nil, 0, errors.Wrapf( + errortypes.ErrInsufficientFee, + "insufficient fees; got: %s required: %s", feeCoins, requiredFees, + ) } } diff --git a/app/evmante_fee_checker_test.go b/app/evmante_fee_checker_test.go new file mode 100644 index 000000000..d4961f011 --- /dev/null +++ b/app/evmante_fee_checker_test.go @@ -0,0 +1,97 @@ +package app_test + +import ( + sdk "github.com/cosmos/cosmos-sdk/types" + + "github.com/NibiruChain/nibiru/app" + "github.com/NibiruChain/nibiru/eth" + "github.com/NibiruChain/nibiru/x/evm/evmtest" +) + +func (s *TestSuite) TestNewDynamicFeeChecker() { + testCases := []struct { + name string + txSetup func(deps *evmtest.TestDeps) sdk.FeeTx + ctxSetup func(deps *evmtest.TestDeps) + wantErr string + wantFee int64 + wantPriority int64 + }{ + { + name: "happy: genesis tx with sufficient fee", + ctxSetup: func(deps *evmtest.TestDeps) { + gasPrice := sdk.NewInt64Coin("unibi", 1) + deps.Ctx = deps.Ctx. + WithBlockHeight(0). + WithMinGasPrices( + sdk.NewDecCoins(sdk.NewDecCoinFromCoin(gasPrice)), + ). + WithIsCheckTx(true) + }, + txSetup: func(deps *evmtest.TestDeps) sdk.FeeTx { + txMsg := happyCreateContractTx(deps) + txBuilder := deps.EncCfg.TxConfig.NewTxBuilder() + tx, err := txMsg.BuildTx(txBuilder, eth.EthBaseDenom) + s.Require().NoError(err) + return tx + }, + wantErr: "", + wantFee: gasLimitCreateContract().Int64(), + wantPriority: 0, + }, + { + name: "sad: genesis tx insufficient fee", + ctxSetup: func(deps *evmtest.TestDeps) { + gasPrice := sdk.NewInt64Coin("unibi", 2) + deps.Ctx = deps.Ctx. + WithBlockHeight(0). + WithMinGasPrices( + sdk.NewDecCoins(sdk.NewDecCoinFromCoin(gasPrice)), + ). + WithIsCheckTx(true) + }, + txSetup: func(deps *evmtest.TestDeps) sdk.FeeTx { + txMsg := happyCreateContractTx(deps) + txBuilder := deps.EncCfg.TxConfig.NewTxBuilder() + tx, err := txMsg.BuildTx(txBuilder, eth.EthBaseDenom) + s.Require().NoError(err) + return tx + }, + wantErr: "insufficient fee", + }, + { + name: "happy: tx with sufficient fee", + txSetup: func(deps *evmtest.TestDeps) sdk.FeeTx { + txMsg := happyCreateContractTx(deps) + txBuilder := deps.EncCfg.TxConfig.NewTxBuilder() + tx, err := txMsg.BuildTx(txBuilder, eth.EthBaseDenom) + s.Require().NoError(err) + return tx + }, + wantErr: "", + wantFee: gasLimitCreateContract().Int64(), + wantPriority: 0, + }, + } + + for _, tc := range testCases { + s.Run(tc.name, func() { + deps := evmtest.NewTestDeps() + checker := app.NewDynamicFeeChecker(deps.K) + + if tc.ctxSetup != nil { + tc.ctxSetup(&deps) + } + + fee, priority, err := checker(deps.Ctx, tc.txSetup(&deps)) + + if tc.wantErr != "" { + s.Require().ErrorContains(err, tc.wantErr) + return + } + s.Require().NoError(err) + s.Require().Equal(tc.wantFee, fee.AmountOf("unibi").Int64()) + s.Require().Equal(tc.wantPriority, priority) + }) + } +}