diff --git a/x/evm/ante/fee.go b/x/evm/ante/fee.go index 7e963d6d6..b85edc2b1 100644 --- a/x/evm/ante/fee.go +++ b/x/evm/ante/fee.go @@ -47,6 +47,9 @@ func (fc EVMFeeCheckDecorator) AnteHandle(ctx sdk.Context, tx sdk.Tx, simulate b if txData.GetGasFeeCap().Cmp(fc.getMinimumFee(ctx)) < 0 { return ctx, sdkerrors.ErrInsufficientFee } + if txData.GetGasTipCap().Sign() < 0 { + return ctx, sdkerrors.Wrapf(sdkerrors.ErrInvalidRequest, "gas fee cap cannot be negative") + } // if EVM version is Cancun or later, and the transaction contains at least one blob, we need to // make sure the transaction carries a non-zero blob fee cap. diff --git a/x/evm/ante/fee_test.go b/x/evm/ante/fee_test.go index 138d22dbd..0d4015e9e 100644 --- a/x/evm/ante/fee_test.go +++ b/x/evm/ante/fee_test.go @@ -112,6 +112,24 @@ func TestEVMFeeCheckDecorator(t *testing.T) { return ctx, nil }) require.NotNil(t, err) + + // should fail because of negative gas tip cap + txData.GasTipCap = big.NewInt(-1) + txData.GasFeeCap = big.NewInt(10000000000000) + tx, err = ethtypes.SignTx(ethtypes.NewTx(&txData), signer, key) + require.Nil(t, err) + typedTx = newDynamicFeeTxWithoutValidation(tx) + msg, err = types.NewMsgEVMTransaction(typedTx) + require.Nil(t, err) + ctx, err = preprocessor.AnteHandle(ctx, mockTx{msgs: []sdk.Msg{msg}}, false, func(ctx sdk.Context, _ sdk.Tx, _ bool) (sdk.Context, error) { + return ctx, nil + }) + require.Nil(t, err) + _, err = handler.AnteHandle(ctx, mockTx{msgs: []sdk.Msg{msg}}, false, func(ctx sdk.Context, _ sdk.Tx, _ bool) (sdk.Context, error) { + return ctx, nil + }) + require.NotNil(t, err) + require.Contains(t, err.Error(), "gas fee cap cannot be negative") } func TestCalculatePriorityScenarios(t *testing.T) { @@ -227,3 +245,22 @@ func TestCalculatePriorityScenarios(t *testing.T) { }) } } + +func newDynamicFeeTxWithoutValidation(tx *ethtypes.Transaction) *ethtx.DynamicFeeTx { + txData := ðtx.DynamicFeeTx{ + Nonce: tx.Nonce(), + Data: tx.Data(), + GasLimit: tx.Gas(), + } + + v, r, s := tx.RawSignatureValues() + ethtx.SetConvertIfPresent(tx.To(), func(to *common.Address) string { return to.Hex() }, txData.SetTo) + ethtx.SetConvertIfPresent(tx.Value(), sdk.NewIntFromBigInt, txData.SetAmount) + ethtx.SetConvertIfPresent(tx.GasFeeCap(), sdk.NewIntFromBigInt, txData.SetGasFeeCap) + ethtx.SetConvertIfPresent(tx.GasTipCap(), sdk.NewIntFromBigInt, txData.SetGasTipCap) + al := tx.AccessList() + ethtx.SetConvertIfPresent(&al, ethtx.NewAccessList, txData.SetAccesses) + + txData.SetSignatureValues(tx.ChainId(), v, r, s) + return txData +}