fix: consistent BaseFee check logic (#855)

Closes: #755

```
if not london_hardfork {
    # reject DynamicFeeTx
    # no `baseFeePerGas` field in block response
    # baseFee = nil
} else {
    # allow DynamicFeeTx
    # add `baseFeePerGas` field in block response
    if feemarketParams.NoBaseFee or height < feemarketParams.EnableHeight {
        # baseFee = 0
    } else {
        # init baseFee to initBaseFee and adjust in later blocks
    }
}
```

Update x/evm/keeper/keeper.go

Co-authored-by: Federico Kunze Küllmer <31522760+fedekunze@users.noreply.github.com>

add unit tests

Update app/ante/utils_test.go

Co-authored-by: Federico Kunze Küllmer <31522760+fedekunze@users.noreply.github.com>

changelog
This commit is contained in:
yihuang 2021-12-28 15:59:28 +08:00 committed by GitHub
parent d822fee5c1
commit eb17366dcc
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
17 changed files with 436 additions and 335 deletions

View File

@ -46,6 +46,7 @@ Ref: https://keepachangelog.com/en/1.0.0/
- (evm) [tharsis#851](https://github.com/tharsis/ethermint/pull/851) fix contract address used in EVM, this issue is caused by [tharsis#808](https://github.com/tharsis/ethermint/issues/808). - (evm) [tharsis#851](https://github.com/tharsis/ethermint/pull/851) fix contract address used in EVM, this issue is caused by [tharsis#808](https://github.com/tharsis/ethermint/issues/808).
- (evm) [tharsis#N/A]() reject invalid `MsgEthereumTx` wrapping tx - (evm) [tharsis#N/A]() reject invalid `MsgEthereumTx` wrapping tx
- (evm) [tharsis#N/A]() Fix SelfDestruct opcode by deleting account code and state - (evm) [tharsis#N/A]() Fix SelfDestruct opcode by deleting account code and state
- (feemarket) [tharsis#855](https://github.com/tharsis/ethermint/pull/855) consistent baseFee check logic
### Improvements ### Improvements

View File

@ -13,7 +13,7 @@ import (
) )
func (suite AnteTestSuite) TestAnteHandler() { func (suite AnteTestSuite) TestAnteHandler() {
suite.dynamicTxFee = false suite.enableFeemarket = false
suite.SetupTest() // reset suite.SetupTest() // reset
addr, privKey := tests.NewAddrKey() addr, privKey := tests.NewAddrKey()
@ -314,22 +314,16 @@ func (suite AnteTestSuite) TestAnteHandler() {
} }
func (suite AnteTestSuite) TestAnteHandlerWithDynamicTxFee() { func (suite AnteTestSuite) TestAnteHandlerWithDynamicTxFee() {
suite.dynamicTxFee = true
suite.SetupTest() // reset
addr, privKey := tests.NewAddrKey() addr, privKey := tests.NewAddrKey()
to := tests.GenerateAddress() to := tests.GenerateAddress()
acc := suite.app.AccountKeeper.NewAccountWithAddress(suite.ctx, addr.Bytes())
suite.Require().NoError(acc.SetSequence(1))
suite.app.AccountKeeper.SetAccount(suite.ctx, acc)
testCases := []struct { testCases := []struct {
name string name string
txFn func() sdk.Tx txFn func() sdk.Tx
checkTx bool enableLondonHF bool
reCheckTx bool checkTx bool
expPass bool reCheckTx bool
expPass bool
}{ }{
{ {
"success - DeliverTx (contract)", "success - DeliverTx (contract)",
@ -351,6 +345,7 @@ func (suite AnteTestSuite) TestAnteHandlerWithDynamicTxFee() {
tx := suite.CreateTestTx(signedContractTx, privKey, 1, false) tx := suite.CreateTestTx(signedContractTx, privKey, 1, false)
return tx return tx
}, },
true,
false, false, true, false, false, true,
}, },
{ {
@ -359,7 +354,7 @@ func (suite AnteTestSuite) TestAnteHandlerWithDynamicTxFee() {
signedContractTx := signedContractTx :=
evmtypes.NewTxContract( evmtypes.NewTxContract(
suite.app.EvmKeeper.ChainID(), suite.app.EvmKeeper.ChainID(),
2, 1,
big.NewInt(10), big.NewInt(10),
100000, 100000,
nil, nil,
@ -373,6 +368,7 @@ func (suite AnteTestSuite) TestAnteHandlerWithDynamicTxFee() {
tx := suite.CreateTestTx(signedContractTx, privKey, 1, false) tx := suite.CreateTestTx(signedContractTx, privKey, 1, false)
return tx return tx
}, },
true,
true, false, true, true, false, true,
}, },
{ {
@ -381,7 +377,7 @@ func (suite AnteTestSuite) TestAnteHandlerWithDynamicTxFee() {
signedContractTx := signedContractTx :=
evmtypes.NewTxContract( evmtypes.NewTxContract(
suite.app.EvmKeeper.ChainID(), suite.app.EvmKeeper.ChainID(),
3, 1,
big.NewInt(10), big.NewInt(10),
100000, 100000,
nil, nil,
@ -395,6 +391,7 @@ func (suite AnteTestSuite) TestAnteHandlerWithDynamicTxFee() {
tx := suite.CreateTestTx(signedContractTx, privKey, 1, false) tx := suite.CreateTestTx(signedContractTx, privKey, 1, false)
return tx return tx
}, },
true,
false, true, true, false, true, true,
}, },
{ {
@ -403,7 +400,7 @@ func (suite AnteTestSuite) TestAnteHandlerWithDynamicTxFee() {
signedTx := signedTx :=
evmtypes.NewTx( evmtypes.NewTx(
suite.app.EvmKeeper.ChainID(), suite.app.EvmKeeper.ChainID(),
4, 1,
&to, &to,
big.NewInt(10), big.NewInt(10),
100000, 100000,
@ -418,6 +415,7 @@ func (suite AnteTestSuite) TestAnteHandlerWithDynamicTxFee() {
tx := suite.CreateTestTx(signedTx, privKey, 1, false) tx := suite.CreateTestTx(signedTx, privKey, 1, false)
return tx return tx
}, },
true,
false, false, true, false, false, true,
}, },
{ {
@ -426,7 +424,7 @@ func (suite AnteTestSuite) TestAnteHandlerWithDynamicTxFee() {
signedTx := signedTx :=
evmtypes.NewTx( evmtypes.NewTx(
suite.app.EvmKeeper.ChainID(), suite.app.EvmKeeper.ChainID(),
5, 1,
&to, &to,
big.NewInt(10), big.NewInt(10),
100000, 100000,
@ -441,6 +439,7 @@ func (suite AnteTestSuite) TestAnteHandlerWithDynamicTxFee() {
tx := suite.CreateTestTx(signedTx, privKey, 1, false) tx := suite.CreateTestTx(signedTx, privKey, 1, false)
return tx return tx
}, },
true,
true, false, true, true, false, true,
}, },
{ {
@ -449,7 +448,7 @@ func (suite AnteTestSuite) TestAnteHandlerWithDynamicTxFee() {
signedTx := signedTx :=
evmtypes.NewTx( evmtypes.NewTx(
suite.app.EvmKeeper.ChainID(), suite.app.EvmKeeper.ChainID(),
3, 1,
&to, &to,
big.NewInt(10), big.NewInt(10),
100000, 100000,
@ -463,7 +462,9 @@ func (suite AnteTestSuite) TestAnteHandlerWithDynamicTxFee() {
tx := suite.CreateTestTx(signedTx, privKey, 1, false) tx := suite.CreateTestTx(signedTx, privKey, 1, false)
return tx return tx
}, false, true, true, },
true,
false, true, true,
}, },
{ {
"success - CheckTx (cosmos tx not signed)", "success - CheckTx (cosmos tx not signed)",
@ -471,7 +472,7 @@ func (suite AnteTestSuite) TestAnteHandlerWithDynamicTxFee() {
signedTx := signedTx :=
evmtypes.NewTx( evmtypes.NewTx(
suite.app.EvmKeeper.ChainID(), suite.app.EvmKeeper.ChainID(),
4, 1,
&to, &to,
big.NewInt(10), big.NewInt(10),
100000, 100000,
@ -485,7 +486,9 @@ func (suite AnteTestSuite) TestAnteHandlerWithDynamicTxFee() {
tx := suite.CreateTestTx(signedTx, privKey, 1, false) tx := suite.CreateTestTx(signedTx, privKey, 1, false)
return tx return tx
}, false, true, true, },
true,
false, true, true,
}, },
{ {
"fail - CheckTx (cosmos tx is not valid)", "fail - CheckTx (cosmos tx is not valid)",
@ -493,7 +496,7 @@ func (suite AnteTestSuite) TestAnteHandlerWithDynamicTxFee() {
signedTx := signedTx :=
evmtypes.NewTx( evmtypes.NewTx(
suite.app.EvmKeeper.ChainID(), suite.app.EvmKeeper.ChainID(),
4, 1,
&to, &to,
big.NewInt(10), big.NewInt(10),
100000, 100000,
@ -509,7 +512,9 @@ func (suite AnteTestSuite) TestAnteHandlerWithDynamicTxFee() {
// bigger than MaxGasWanted // bigger than MaxGasWanted
txBuilder.SetGasLimit(uint64(1 << 63)) txBuilder.SetGasLimit(uint64(1 << 63))
return txBuilder.GetTx() return txBuilder.GetTx()
}, true, false, false, },
true,
true, false, false,
}, },
{ {
"fail - CheckTx (memo too long)", "fail - CheckTx (memo too long)",
@ -517,7 +522,7 @@ func (suite AnteTestSuite) TestAnteHandlerWithDynamicTxFee() {
signedTx := signedTx :=
evmtypes.NewTx( evmtypes.NewTx(
suite.app.EvmKeeper.ChainID(), suite.app.EvmKeeper.ChainID(),
5, 1,
&to, &to,
big.NewInt(10), big.NewInt(10),
100000, 100000,
@ -532,12 +537,45 @@ func (suite AnteTestSuite) TestAnteHandlerWithDynamicTxFee() {
txBuilder := suite.CreateTestTxBuilder(signedTx, privKey, 1, false) txBuilder := suite.CreateTestTxBuilder(signedTx, privKey, 1, false)
txBuilder.SetMemo(strings.Repeat("*", 257)) txBuilder.SetMemo(strings.Repeat("*", 257))
return txBuilder.GetTx() return txBuilder.GetTx()
}, true, false, false, },
true,
true, false, false,
},
{
"fail - DynamicFeeTx without london hark fork",
func() sdk.Tx {
signedContractTx :=
evmtypes.NewTxContract(
suite.app.EvmKeeper.ChainID(),
1,
big.NewInt(10),
100000,
nil,
big.NewInt(ethparams.InitialBaseFee+1),
big.NewInt(1),
nil,
&types.AccessList{},
)
signedContractTx.From = addr.Hex()
tx := suite.CreateTestTx(signedContractTx, privKey, 1, false)
return tx
},
false,
false, false, false,
}, },
} }
for _, tc := range testCases { for _, tc := range testCases {
suite.Run(tc.name, func() { suite.Run(tc.name, func() {
suite.enableFeemarket = true
suite.enableLondonHF = tc.enableLondonHF
suite.SetupTest() // reset
acc := suite.app.AccountKeeper.NewAccountWithAddress(suite.ctx, addr.Bytes())
suite.Require().NoError(acc.SetSequence(1))
suite.app.AccountKeeper.SetAccount(suite.ctx, acc)
suite.ctx = suite.ctx.WithIsCheckTx(tc.checkTx).WithIsReCheckTx(tc.reCheckTx) suite.ctx = suite.ctx.WithIsCheckTx(tc.checkTx).WithIsReCheckTx(tc.reCheckTx)
suite.app.EvmKeeper.AddBalance(addr, big.NewInt((ethparams.InitialBaseFee+10)*100000)) suite.app.EvmKeeper.AddBalance(addr, big.NewInt((ethparams.InitialBaseFee+10)*100000))
_, err := suite.anteHandler(suite.ctx, tc.txFn(), false) _, err := suite.anteHandler(suite.ctx, tc.txFn(), false)
@ -548,5 +586,6 @@ func (suite AnteTestSuite) TestAnteHandlerWithDynamicTxFee() {
} }
}) })
} }
suite.dynamicTxFee = false suite.enableFeemarket = false
suite.enableLondonHF = true
} }

View File

@ -17,6 +17,7 @@ import (
"github.com/ethereum/go-ethereum/core" "github.com/ethereum/go-ethereum/core"
ethtypes "github.com/ethereum/go-ethereum/core/types" ethtypes "github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/core/vm" "github.com/ethereum/go-ethereum/core/vm"
"github.com/ethereum/go-ethereum/params"
) )
// EVMKeeper defines the expected keeper interface used on the Eth AnteHandler // EVMKeeper defines the expected keeper interface used on the Eth AnteHandler
@ -32,6 +33,7 @@ type EVMKeeper interface {
DeductTxCostsFromUserBalance( DeductTxCostsFromUserBalance(
ctx sdk.Context, msgEthTx evmtypes.MsgEthereumTx, txData evmtypes.TxData, denom string, homestead, istanbul, london bool, ctx sdk.Context, msgEthTx evmtypes.MsgEthereumTx, txData evmtypes.TxData, denom string, homestead, istanbul, london bool,
) (sdk.Coins, error) ) (sdk.Coins, error)
BaseFee(ctx sdk.Context, ethCfg *params.ChainConfig) *big.Int
} }
type protoTxProvider interface { type protoTxProvider interface {
@ -326,8 +328,6 @@ func (ctd CanTransferDecorator) AnteHandle(ctx sdk.Context, tx sdk.Tx, simulate
ctd.evmKeeper.WithContext(ctx) ctd.evmKeeper.WithContext(ctx)
params := ctd.evmKeeper.GetParams(ctx) params := ctd.evmKeeper.GetParams(ctx)
feeMktParams := ctd.feemarketKeeper.GetParams(ctx)
ethCfg := params.ChainConfig.EthereumConfig(ctd.evmKeeper.ChainID()) ethCfg := params.ChainConfig.EthereumConfig(ctd.evmKeeper.ChainID())
signer := ethtypes.MakeSigner(ethCfg, big.NewInt(ctx.BlockHeight())) signer := ethtypes.MakeSigner(ethCfg, big.NewInt(ctx.BlockHeight()))
@ -337,10 +337,7 @@ func (ctd CanTransferDecorator) AnteHandle(ctx sdk.Context, tx sdk.Tx, simulate
return ctx, sdkerrors.Wrapf(sdkerrors.ErrUnknownRequest, "invalid transaction type %T, expected %T", tx, (*evmtypes.MsgEthereumTx)(nil)) return ctx, sdkerrors.Wrapf(sdkerrors.ErrUnknownRequest, "invalid transaction type %T, expected %T", tx, (*evmtypes.MsgEthereumTx)(nil))
} }
var baseFee *big.Int baseFee := ctd.evmKeeper.BaseFee(ctx, ethCfg)
if evmtypes.IsLondon(ethCfg, ctx.BlockHeight()) && !feeMktParams.NoBaseFee {
baseFee = ctd.feemarketKeeper.GetBaseFee(ctx)
}
coreMsg, err := msgEthTx.AsMessage(signer, baseFee) coreMsg, err := msgEthTx.AsMessage(signer, baseFee)
if err != nil { if err != nil {
@ -370,17 +367,23 @@ func (ctd CanTransferDecorator) AnteHandle(ctx sdk.Context, tx sdk.Tx, simulate
) )
} }
if evmtypes.IsLondon(ethCfg, ctx.BlockHeight()) && !feeMktParams.NoBaseFee && baseFee == nil { if evmtypes.IsLondon(ethCfg, ctx.BlockHeight()) {
return ctx, sdkerrors.Wrap(evmtypes.ErrInvalidBaseFee, "base fee is supported but evm block context value is nil") if baseFee == nil {
} return ctx, sdkerrors.Wrap(
evmtypes.ErrInvalidBaseFee,
if evmtypes.IsLondon(ethCfg, ctx.BlockHeight()) && !feeMktParams.NoBaseFee && baseFee != nil && coreMsg.GasFeeCap().Cmp(baseFee) < 0 { "base fee is supported but evm block context value is nil",
return ctx, sdkerrors.Wrapf(evmtypes.ErrInvalidBaseFee, "max fee per gas less than block base fee (%s < %s)", coreMsg.GasFeeCap(), baseFee) )
}
if coreMsg.GasFeeCap().Cmp(baseFee) < 0 {
return ctx, sdkerrors.Wrapf(
evmtypes.ErrInvalidBaseFee,
"max fee per gas less than block base fee (%s < %s)",
coreMsg.GasFeeCap(), baseFee,
)
}
} }
} }
ctd.evmKeeper.WithContext(ctx)
// set the original gas meter // set the original gas meter
return next(ctx, tx, simulate) return next(ctx, tx, simulate)
} }
@ -443,6 +446,8 @@ func (vbd EthValidateBasicDecorator) AnteHandle(ctx sdk.Context, tx sdk.Tx, simu
return next(ctx, tx, simulate) return next(ctx, tx, simulate)
} }
vbd.evmKeeper.WithContext(ctx)
err := tx.ValidateBasic() err := tx.ValidateBasic()
// ErrNoSignatures is fine with eth tx // ErrNoSignatures is fine with eth tx
if err != nil && !errors.Is(err, sdkerrors.ErrNoSignatures) { if err != nil && !errors.Is(err, sdkerrors.ErrNoSignatures) {
@ -477,7 +482,15 @@ func (vbd EthValidateBasicDecorator) AnteHandle(ctx sdk.Context, tx sdk.Tx, simu
if err != nil { if err != nil {
return ctx, sdkerrors.Wrap(err, "failed to unpack MsgEthereumTx Data") return ctx, sdkerrors.Wrap(err, "failed to unpack MsgEthereumTx Data")
} }
params := vbd.evmKeeper.GetParams(ctx) params := vbd.evmKeeper.GetParams(ctx)
chainID := vbd.evmKeeper.ChainID()
ethCfg := params.ChainConfig.EthereumConfig(chainID)
baseFee := vbd.evmKeeper.BaseFee(ctx, ethCfg)
if baseFee == nil && txData.TxType() == ethtypes.DynamicFeeTxType {
return ctx, sdkerrors.Wrap(ethtypes.ErrTxTypeNotSupported, "dynamic fee tx not supported")
}
ethFeeAmount := sdk.Coins{sdk.NewCoin(params.EvmDenom, sdk.NewIntFromBigInt(txData.Fee()))} ethFeeAmount := sdk.Coins{sdk.NewCoin(params.EvmDenom, sdk.NewIntFromBigInt(txData.Fee()))}
authInfo := protoTx.AuthInfo authInfo := protoTx.AuthInfo
@ -558,13 +571,12 @@ func (mfd EthMempoolFeeDecorator) AnteHandle(ctx sdk.Context, tx sdk.Tx, simulat
var feeAmt *big.Int var feeAmt *big.Int
feeMktParams := mfd.feemarketKeeper.GetParams(ctx)
params := mfd.evmKeeper.GetParams(ctx) params := mfd.evmKeeper.GetParams(ctx)
chainID := mfd.evmKeeper.ChainID() chainID := mfd.evmKeeper.ChainID()
ethCfg := params.ChainConfig.EthereumConfig(chainID) ethCfg := params.ChainConfig.EthereumConfig(chainID)
evmDenom := params.EvmDenom evmDenom := params.EvmDenom
if evmtypes.IsLondon(ethCfg, ctx.BlockHeight()) && !feeMktParams.NoBaseFee { baseFee := mfd.evmKeeper.BaseFee(ctx, ethCfg)
baseFee := mfd.feemarketKeeper.GetBaseFee(ctx) if baseFee != nil {
feeAmt = msg.GetEffectiveFee(baseFee) feeAmt = msg.GetEffectiveFee(baseFee)
} else { } else {
feeAmt = msg.GetFee() feeAmt = msg.GetFee()

View File

@ -8,7 +8,7 @@ import (
) )
func (suite AnteTestSuite) TestSignatures() { func (suite AnteTestSuite) TestSignatures() {
suite.dynamicTxFee = false suite.enableFeemarket = false
suite.SetupTest() // reset suite.SetupTest() // reset
addr, privKey := tests.NewAddrKey() addr, privKey := tests.NewAddrKey()

View File

@ -1,6 +1,7 @@
package ante_test package ante_test
import ( import (
"math"
"testing" "testing"
"time" "time"
@ -12,6 +13,7 @@ import (
"github.com/cosmos/cosmos-sdk/client/tx" "github.com/cosmos/cosmos-sdk/client/tx"
codectypes "github.com/cosmos/cosmos-sdk/codec/types" codectypes "github.com/cosmos/cosmos-sdk/codec/types"
cryptotypes "github.com/cosmos/cosmos-sdk/crypto/types" cryptotypes "github.com/cosmos/cosmos-sdk/crypto/types"
"github.com/cosmos/cosmos-sdk/simapp"
"github.com/cosmos/cosmos-sdk/testutil/testdata" "github.com/cosmos/cosmos-sdk/testutil/testdata"
sdk "github.com/cosmos/cosmos-sdk/types" sdk "github.com/cosmos/cosmos-sdk/types"
"github.com/cosmos/cosmos-sdk/types/tx/signing" "github.com/cosmos/cosmos-sdk/types/tx/signing"
@ -32,27 +34,38 @@ import (
type AnteTestSuite struct { type AnteTestSuite struct {
suite.Suite suite.Suite
ctx sdk.Context ctx sdk.Context
app *app.EthermintApp app *app.EthermintApp
clientCtx client.Context clientCtx client.Context
anteHandler sdk.AnteHandler anteHandler sdk.AnteHandler
ethSigner ethtypes.Signer ethSigner ethtypes.Signer
dynamicTxFee bool enableFeemarket bool
enableLondonHF bool
} }
func (suite *AnteTestSuite) SetupTest() { func (suite *AnteTestSuite) SetupTest() {
checkTx := false checkTx := false
if suite.dynamicTxFee { suite.app = app.Setup(checkTx, func(app *app.EthermintApp, genesis simapp.GenesisState) simapp.GenesisState {
// setup feemarketGenesis params if suite.enableFeemarket {
feemarketGenesis := feemarkettypes.DefaultGenesisState() // setup feemarketGenesis params
feemarketGenesis.Params.EnableHeight = 1 feemarketGenesis := feemarkettypes.DefaultGenesisState()
feemarketGenesis.Params.NoBaseFee = false feemarketGenesis.Params.EnableHeight = 1
feemarketGenesis.BaseFee = sdk.NewInt(feemarketGenesis.Params.InitialBaseFee) feemarketGenesis.Params.NoBaseFee = false
suite.app = app.Setup(checkTx, feemarketGenesis) feemarketGenesis.BaseFee = sdk.NewInt(feemarketGenesis.Params.InitialBaseFee)
} else { // Verify feeMarket genesis
suite.app = app.Setup(checkTx, nil) err := feemarketGenesis.Validate()
} suite.Require().NoError(err)
genesis[feemarkettypes.ModuleName] = app.AppCodec().MustMarshalJSON(feemarketGenesis)
}
if !suite.enableLondonHF {
evmGenesis := evmtypes.DefaultGenesisState()
maxInt := sdk.NewInt(math.MaxInt64)
evmGenesis.Params.ChainConfig.LondonBlock = &maxInt
genesis[evmtypes.ModuleName] = app.AppCodec().MustMarshalJSON(evmGenesis)
}
return genesis
})
suite.ctx = suite.app.BaseApp.NewContext(checkTx, tmproto.Header{Height: 2, ChainID: "ethermint_9000-1", Time: time.Now().UTC()}) suite.ctx = suite.app.BaseApp.NewContext(checkTx, tmproto.Header{Height: 2, ChainID: "ethermint_9000-1", Time: time.Now().UTC()})
suite.ctx = suite.ctx.WithMinGasPrices(sdk.NewDecCoins(sdk.NewDecCoin(evmtypes.DefaultEVMDenom, sdk.OneInt()))) suite.ctx = suite.ctx.WithMinGasPrices(sdk.NewDecCoins(sdk.NewDecCoin(evmtypes.DefaultEVMDenom, sdk.OneInt())))
@ -61,7 +74,6 @@ func (suite *AnteTestSuite) SetupTest() {
infCtx := suite.ctx.WithGasMeter(sdk.NewInfiniteGasMeter()) infCtx := suite.ctx.WithGasMeter(sdk.NewInfiniteGasMeter())
suite.app.AccountKeeper.SetParams(infCtx, authtypes.DefaultParams()) suite.app.AccountKeeper.SetParams(infCtx, authtypes.DefaultParams())
suite.app.EvmKeeper.SetParams(infCtx, evmtypes.DefaultParams())
encodingConfig := encoding.MakeConfig(app.ModuleBasics) encodingConfig := encoding.MakeConfig(app.ModuleBasics)
// We're using TestMsg amino encoding in some tests, so register it here. // We're using TestMsg amino encoding in some tests, so register it here.
@ -78,7 +90,9 @@ func (suite *AnteTestSuite) SetupTest() {
} }
func TestAnteTestSuite(t *testing.T) { func TestAnteTestSuite(t *testing.T) {
suite.Run(t, new(AnteTestSuite)) suite.Run(t, &AnteTestSuite{
enableLondonHF: true,
})
} }
// CreateTestTx is a helper function to create a tx given multiple inputs. // CreateTestTx is a helper function to create a tx given multiple inputs.

View File

@ -12,7 +12,6 @@ import (
tmproto "github.com/tendermint/tendermint/proto/tendermint/types" tmproto "github.com/tendermint/tendermint/proto/tendermint/types"
tmtypes "github.com/tendermint/tendermint/types" tmtypes "github.com/tendermint/tendermint/types"
dbm "github.com/tendermint/tm-db" dbm "github.com/tendermint/tm-db"
feemarkettypes "github.com/tharsis/ethermint/x/feemarket/types"
) )
// DefaultConsensusParams defines the default Tendermint consensus params used in // DefaultConsensusParams defines the default Tendermint consensus params used in
@ -35,20 +34,14 @@ var DefaultConsensusParams = &abci.ConsensusParams{
} }
// Setup initializes a new EthermintApp. A Nop logger is set in EthermintApp. // Setup initializes a new EthermintApp. A Nop logger is set in EthermintApp.
func Setup(isCheckTx bool, feemarketGenesis *feemarkettypes.GenesisState) *EthermintApp { func Setup(isCheckTx bool, patchGenesis func(*EthermintApp, simapp.GenesisState) simapp.GenesisState) *EthermintApp {
db := dbm.NewMemDB() db := dbm.NewMemDB()
app := NewEthermintApp(log.NewNopLogger(), db, nil, true, map[int64]bool{}, DefaultNodeHome, 5, encoding.MakeConfig(ModuleBasics), simapp.EmptyAppOptions{}) app := NewEthermintApp(log.NewNopLogger(), db, nil, true, map[int64]bool{}, DefaultNodeHome, 5, encoding.MakeConfig(ModuleBasics), simapp.EmptyAppOptions{})
if !isCheckTx { if !isCheckTx {
// init chain must be called to stop deliverState from being nil // init chain must be called to stop deliverState from being nil
genesisState := NewDefaultGenesisState() genesisState := NewDefaultGenesisState()
if patchGenesis != nil {
// Verify feeMarket genesis genesisState = patchGenesis(app, genesisState)
if feemarketGenesis != nil {
if err := feemarketGenesis.Validate(); err != nil {
panic(err)
}
genesisState[feemarkettypes.ModuleName] = app.AppCodec().MustMarshalJSON(feemarketGenesis)
} }
stateBytes, err := json.MarshalIndent(genesisState, "", " ") stateBytes, err := json.MarshalIndent(genesisState, "", " ")

View File

@ -74,14 +74,15 @@ func (suite *EvmTestSuite) DoSetupTest(t require.TestingT) {
require.NoError(t, err) require.NoError(t, err)
consAddress := sdk.ConsAddress(priv.PubKey().Address()) consAddress := sdk.ConsAddress(priv.PubKey().Address())
if suite.dynamicTxFee { suite.app = app.Setup(checkTx, func(app *app.EthermintApp, genesis simapp.GenesisState) simapp.GenesisState {
feemarketGenesis := feemarkettypes.DefaultGenesisState() if suite.dynamicTxFee {
feemarketGenesis.Params.EnableHeight = 1 feemarketGenesis := feemarkettypes.DefaultGenesisState()
feemarketGenesis.Params.NoBaseFee = false feemarketGenesis.Params.EnableHeight = 1
suite.app = app.Setup(checkTx, feemarketGenesis) feemarketGenesis.Params.NoBaseFee = false
} else { genesis[feemarkettypes.ModuleName] = app.AppCodec().MustMarshalJSON(feemarketGenesis)
suite.app = app.Setup(checkTx, nil) }
} return genesis
})
coins := sdk.NewCoins(sdk.NewCoin(types.DefaultEVMDenom, sdk.NewInt(100000000000000))) coins := sdk.NewCoins(sdk.NewCoin(types.DefaultEVMDenom, sdk.NewInt(100000000000000)))
genesisState := app.ModuleBasics.DefaultGenesis(suite.app.AppCodec()) genesisState := app.ModuleBasics.DefaultGenesis(suite.app.AppCodec())

View File

@ -220,20 +220,17 @@ func (k Keeper) EthCall(c context.Context, req *types.EthCallRequest) (*types.Ms
return nil, status.Error(codes.InvalidArgument, err.Error()) return nil, status.Error(codes.InvalidArgument, err.Error())
} }
params := k.GetParams(ctx) cfg, err := k.EVMConfig(ctx)
ethCfg := params.ChainConfig.EthereumConfig(k.eip155ChainID) if err != nil {
return nil, status.Error(codes.Internal, err.Error())
var baseFee *big.Int
if types.IsLondon(ethCfg, ctx.BlockHeight()) {
baseFee = k.feeMarketKeeper.GetBaseFee(ctx)
} }
msg, err := args.ToMessage(req.GasCap, baseFee) msg, err := args.ToMessage(req.GasCap, cfg.BaseFee)
if err != nil { if err != nil {
return nil, status.Error(codes.InvalidArgument, err.Error()) return nil, status.Error(codes.InvalidArgument, err.Error())
} }
res, err := k.ApplyMessage(msg, nil, false) res, err := k.ApplyMessageWithConfig(msg, nil, false, cfg)
if err != nil { if err != nil {
return nil, status.Error(codes.Internal, err.Error()) return nil, status.Error(codes.Internal, err.Error())
} }
@ -292,10 +289,6 @@ func (k Keeper) EstimateGas(c context.Context, req *types.EthCallRequest) (*type
if err != nil { if err != nil {
return nil, status.Error(codes.Internal, "failed to load evm config") return nil, status.Error(codes.Internal, "failed to load evm config")
} }
var baseFee *big.Int
if types.IsLondon(cfg.ChainConfig, ctx.BlockHeight()) {
baseFee = k.feeMarketKeeper.GetBaseFee(ctx)
}
// Create a helper to check if a gas allowance results in an executable transaction // Create a helper to check if a gas allowance results in an executable transaction
executable := func(gas uint64) (vmerror bool, rsp *types.MsgEthereumTxResponse, err error) { executable := func(gas uint64) (vmerror bool, rsp *types.MsgEthereumTxResponse, err error) {
@ -304,7 +297,7 @@ func (k Keeper) EstimateGas(c context.Context, req *types.EthCallRequest) (*type
// Reset to the initial context // Reset to the initial context
k.WithContext(ctx) k.WithContext(ctx)
msg, err := args.ToMessage(req.GasCap, baseFee) msg, err := args.ToMessage(req.GasCap, cfg.BaseFee)
if err != nil { if err != nil {
return false, nil, err return false, nil, err
} }
@ -364,27 +357,28 @@ func (k Keeper) TraceTx(c context.Context, req *types.QueryTraceTxRequest) (*typ
ctx = ctx.WithHeaderHash(common.Hex2Bytes(req.BlockHash)) ctx = ctx.WithHeaderHash(common.Hex2Bytes(req.BlockHash))
k.WithContext(ctx) k.WithContext(ctx)
params := k.GetParams(ctx) cfg, err := k.EVMConfig(ctx)
ethCfg := params.ChainConfig.EthereumConfig(k.eip155ChainID) if err != nil {
signer := ethtypes.MakeSigner(ethCfg, big.NewInt(ctx.BlockHeight())) return nil, status.Error(codes.Internal, "failed to load evm config")
baseFee := k.feeMarketKeeper.GetBaseFee(ctx) }
signer := ethtypes.MakeSigner(cfg.ChainConfig, big.NewInt(ctx.BlockHeight()))
for i, tx := range req.Predecessors { for i, tx := range req.Predecessors {
ethTx := tx.AsTransaction() ethTx := tx.AsTransaction()
msg, err := ethTx.AsMessage(signer, baseFee) msg, err := ethTx.AsMessage(signer, cfg.BaseFee)
if err != nil { if err != nil {
continue continue
} }
k.SetTxHashTransient(ethTx.Hash()) k.SetTxHashTransient(ethTx.Hash())
k.SetTxIndexTransient(uint64(i)) k.SetTxIndexTransient(uint64(i))
if _, err := k.ApplyMessage(msg, types.NewNoOpTracer(), true); err != nil { if _, err := k.ApplyMessageWithConfig(msg, types.NewNoOpTracer(), true, cfg); err != nil {
continue continue
} }
} }
tx := req.Msg.AsTransaction() tx := req.Msg.AsTransaction()
result, err := k.traceTx(ctx, signer, req.TxIndex, ethCfg, tx, baseFee, req.TraceConfig, false) result, err := k.traceTx(ctx, cfg, signer, req.TxIndex, tx, req.TraceConfig, false)
if err != nil { if err != nil {
// error will be returned with detail status from traceTx // error will be returned with detail status from traceTx
return nil, err return nil, err
@ -418,18 +412,18 @@ func (k Keeper) TraceBlock(c context.Context, req *types.QueryTraceBlockRequest)
ctx = ctx.WithHeaderHash(common.Hex2Bytes(req.BlockHash)) ctx = ctx.WithHeaderHash(common.Hex2Bytes(req.BlockHash))
k.WithContext(ctx) k.WithContext(ctx)
params := k.GetParams(ctx) cfg, err := k.EVMConfig(ctx)
ethCfg := params.ChainConfig.EthereumConfig(k.eip155ChainID) if err != nil {
signer := ethtypes.MakeSigner(ethCfg, big.NewInt(ctx.BlockHeight())) return nil, status.Error(codes.Internal, "failed to load evm config")
baseFee := k.feeMarketKeeper.GetBaseFee(ctx) }
signer := ethtypes.MakeSigner(cfg.ChainConfig, big.NewInt(ctx.BlockHeight()))
txsLength := len(req.Txs) txsLength := len(req.Txs)
results := make([]*types.TxTraceResult, 0, txsLength) results := make([]*types.TxTraceResult, 0, txsLength)
for i, tx := range req.Txs { for i, tx := range req.Txs {
result := types.TxTraceResult{} result := types.TxTraceResult{}
ethTx := tx.AsTransaction() ethTx := tx.AsTransaction()
traceResult, err := k.traceTx(ctx, signer, uint64(i), ethCfg, ethTx, baseFee, req.TraceConfig, true) traceResult, err := k.traceTx(ctx, cfg, signer, uint64(i), ethTx, req.TraceConfig, true)
if err != nil { if err != nil {
result.Error = err.Error() result.Error = err.Error()
continue continue
@ -450,11 +444,10 @@ func (k Keeper) TraceBlock(c context.Context, req *types.QueryTraceBlockRequest)
func (k *Keeper) traceTx( func (k *Keeper) traceTx(
ctx sdk.Context, ctx sdk.Context,
cfg *types.EVMConfig,
signer ethtypes.Signer, signer ethtypes.Signer,
txIndex uint64, txIndex uint64,
ethCfg *ethparams.ChainConfig,
tx *ethtypes.Transaction, tx *ethtypes.Transaction,
baseFee *big.Int,
traceConfig *types.TraceConfig, traceConfig *types.TraceConfig,
commitMessage bool, commitMessage bool,
) (*interface{}, error) { ) (*interface{}, error) {
@ -465,7 +458,7 @@ func (k *Keeper) traceTx(
err error err error
) )
msg, err := tx.AsMessage(signer, baseFee) msg, err := tx.AsMessage(signer, cfg.BaseFee)
if err != nil { if err != nil {
return nil, status.Error(codes.Internal, err.Error()) return nil, status.Error(codes.Internal, err.Error())
} }
@ -473,7 +466,7 @@ func (k *Keeper) traceTx(
txHash := tx.Hash() txHash := tx.Hash()
if traceConfig != nil && traceConfig.Overrides != nil { if traceConfig != nil && traceConfig.Overrides != nil {
overrides = traceConfig.Overrides.EthereumConfig(ethCfg.ChainID) overrides = traceConfig.Overrides.EthereumConfig(cfg.ChainConfig.ChainID)
} }
switch { switch {
@ -522,13 +515,13 @@ func (k *Keeper) traceTx(
} }
tracer = vm.NewStructLogger(&logConfig) tracer = vm.NewStructLogger(&logConfig)
default: default:
tracer = types.NewTracer(types.TracerStruct, msg, ethCfg, ctx.BlockHeight()) tracer = types.NewTracer(types.TracerStruct, msg, cfg.ChainConfig, ctx.BlockHeight())
} }
k.SetTxHashTransient(txHash) k.SetTxHashTransient(txHash)
k.SetTxIndexTransient(txIndex) k.SetTxIndexTransient(txIndex)
res, err := k.ApplyMessage(msg, tracer, commitMessage) res, err := k.ApplyMessageWithConfig(msg, tracer, commitMessage, cfg)
if err != nil { if err != nil {
return nil, status.Error(codes.Internal, err.Error()) return nil, status.Error(codes.Internal, err.Error())
} }

View File

@ -485,11 +485,11 @@ func (suite *KeeperTestSuite) TestEstimateGas() {
gasCap uint64 gasCap uint64
) )
testCases := []struct { testCases := []struct {
msg string msg string
malleate func() malleate func()
expPass bool expPass bool
expGas uint64 expGas uint64
dynamicTxFee bool enableFeemarket bool
}{ }{
// should success, because transfer value is zero // should success, because transfer value is zero
{"default args", func() { {"default args", func() {
@ -531,24 +531,24 @@ func (suite *KeeperTestSuite) TestEstimateGas() {
args = types.TransactionArgs{To: &contractAddr, From: &suite.address, Data: (*hexutil.Bytes)(&transferData)} args = types.TransactionArgs{To: &contractAddr, From: &suite.address, Data: (*hexutil.Bytes)(&transferData)}
}, true, 51880, false}, }, true, 51880, false},
// repeated tests with dynamicTxFee // repeated tests with enableFeemarket
{"default args w/ dynamicTxFee", func() { {"default args w/ enableFeemarket", func() {
args = types.TransactionArgs{To: &common.Address{}} args = types.TransactionArgs{To: &common.Address{}}
}, true, 21000, true}, }, true, 21000, true},
{"not enough balance w/ dynamicTxFee", func() { {"not enough balance w/ enableFeemarket", func() {
args = types.TransactionArgs{To: &common.Address{}, Value: (*hexutil.Big)(big.NewInt(100))} args = types.TransactionArgs{To: &common.Address{}, Value: (*hexutil.Big)(big.NewInt(100))}
}, false, 0, true}, }, false, 0, true},
{"enough balance w/ dynamicTxFee", func() { {"enough balance w/ enableFeemarket", func() {
args = types.TransactionArgs{To: &common.Address{}, From: &suite.address, Value: (*hexutil.Big)(big.NewInt(100))} args = types.TransactionArgs{To: &common.Address{}, From: &suite.address, Value: (*hexutil.Big)(big.NewInt(100))}
}, false, 0, true}, }, false, 0, true},
{"gas exceed allowance w/ dynamicTxFee", func() { {"gas exceed allowance w/ enableFeemarket", func() {
args = types.TransactionArgs{To: &common.Address{}, Gas: &gasHelper} args = types.TransactionArgs{To: &common.Address{}, Gas: &gasHelper}
}, true, 21000, true}, }, true, 21000, true},
{"gas exceed global allowance w/ dynamicTxFee", func() { {"gas exceed global allowance w/ enableFeemarket", func() {
args = types.TransactionArgs{To: &common.Address{}} args = types.TransactionArgs{To: &common.Address{}}
gasCap = 20000 gasCap = 20000
}, false, 0, true}, }, false, 0, true},
{"contract deployment w/ dynamicTxFee", func() { {"contract deployment w/ enableFeemarket", func() {
ctorArgs, err := types.ERC20Contract.ABI.Pack("", &suite.address, sdk.NewIntWithDecimal(1000, 18).BigInt()) ctorArgs, err := types.ERC20Contract.ABI.Pack("", &suite.address, sdk.NewIntWithDecimal(1000, 18).BigInt())
suite.Require().NoError(err) suite.Require().NoError(err)
data := append(types.ERC20Contract.Bin, ctorArgs...) data := append(types.ERC20Contract.Bin, ctorArgs...)
@ -557,7 +557,7 @@ func (suite *KeeperTestSuite) TestEstimateGas() {
Data: (*hexutil.Bytes)(&data), Data: (*hexutil.Bytes)(&data),
} }
}, true, 1186778, true}, }, true, 1186778, true},
{"erc20 transfer w/ dynamicTxFee", func() { {"erc20 transfer w/ enableFeemarket", func() {
contractAddr := suite.DeployTestContract(suite.T(), suite.address, sdk.NewIntWithDecimal(1000, 18).BigInt()) contractAddr := suite.DeployTestContract(suite.T(), suite.address, sdk.NewIntWithDecimal(1000, 18).BigInt())
suite.Commit() suite.Commit()
transferData, err := types.ERC20Contract.ABI.Pack("transfer", common.HexToAddress("0x378c50D9264C63F3F92B806d4ee56E9D86FfB3Ec"), big.NewInt(1000)) transferData, err := types.ERC20Contract.ABI.Pack("transfer", common.HexToAddress("0x378c50D9264C63F3F92B806d4ee56E9D86FfB3Ec"), big.NewInt(1000))
@ -568,7 +568,7 @@ func (suite *KeeperTestSuite) TestEstimateGas() {
for _, tc := range testCases { for _, tc := range testCases {
suite.Run(fmt.Sprintf("Case %s", tc.msg), func() { suite.Run(fmt.Sprintf("Case %s", tc.msg), func() {
suite.dynamicTxFee = tc.dynamicTxFee suite.enableFeemarket = tc.enableFeemarket
suite.SetupTest() suite.SetupTest()
gasCap = 25_000_000 gasCap = 25_000_000
tc.malleate() tc.malleate()
@ -589,7 +589,7 @@ func (suite *KeeperTestSuite) TestEstimateGas() {
} }
}) })
} }
suite.dynamicTxFee = false // reset flag suite.enableFeemarket = false // reset flag
} }
func (suite *KeeperTestSuite) TestTraceTx() { func (suite *KeeperTestSuite) TestTraceTx() {
@ -602,11 +602,11 @@ func (suite *KeeperTestSuite) TestTraceTx() {
) )
testCases := []struct { testCases := []struct {
msg string msg string
malleate func() malleate func()
expPass bool expPass bool
traceResponse []byte traceResponse []byte
dynamicTxFee bool enableFeemarket bool
}{ }{
{ {
msg: "default trace", msg: "default trace",
@ -629,9 +629,9 @@ func (suite *KeeperTestSuite) TestTraceTx() {
} }
predecessors = []*types.MsgEthereumTx{} predecessors = []*types.MsgEthereumTx{}
}, },
expPass: true, expPass: true,
traceResponse: []byte{0x7b, 0x22, 0x67, 0x61, 0x73, 0x22, 0x3a, 0x33, 0x34, 0x38, 0x32, 0x38, 0x2c, 0x22, 0x66, 0x61, 0x69, 0x6c, 0x65, 0x64, 0x22, 0x3a, 0x66, 0x61, 0x6c, 0x73, 0x65, 0x2c, 0x22, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x22, 0x3a, 0x22, 0x22, 0x2c, 0x22, 0x73, 0x74, 0x72, 0x75, 0x63, 0x74, 0x4c, 0x6f, 0x67, 0x73, 0x22, 0x3a, 0x5b, 0x7b, 0x22, 0x70, 0x63, 0x22, 0x3a, 0x30, 0x2c, 0x22, 0x6f, 0x70, 0x22, 0x3a, 0x22, 0x50, 0x55, 0x53, 0x48, 0x31, 0x22, 0x2c, 0x22, 0x67, 0x61, 0x73, 0x22, 0x3a, 0x33, 0x30, 0x32, 0x39, 0x36, 0x2c, 0x22, 0x67, 0x61, 0x73, 0x43, 0x6f, 0x73, 0x74, 0x22, 0x3a, 0x33, 0x2c, 0x22, 0x64, 0x65, 0x70, 0x74, 0x68, 0x22, 0x3a, 0x31, 0x7d, 0x2c, 0x7b, 0x22, 0x70, 0x63, 0x22, 0x3a, 0x32, 0x2c, 0x22, 0x6f, 0x70, 0x22, 0x3a, 0x22, 0x50, 0x55, 0x53, 0x48, 0x31, 0x22, 0x2c, 0x22, 0x67, 0x61, 0x73, 0x22, 0x3a, 0x33, 0x30, 0x32, 0x39, 0x33, 0x2c, 0x22, 0x67}, traceResponse: []byte{0x7b, 0x22, 0x67, 0x61, 0x73, 0x22, 0x3a, 0x33, 0x34, 0x38, 0x32, 0x38, 0x2c, 0x22, 0x66, 0x61, 0x69, 0x6c, 0x65, 0x64, 0x22, 0x3a, 0x66, 0x61, 0x6c, 0x73, 0x65, 0x2c, 0x22, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x22, 0x3a, 0x22, 0x22, 0x2c, 0x22, 0x73, 0x74, 0x72, 0x75, 0x63, 0x74, 0x4c, 0x6f, 0x67, 0x73, 0x22, 0x3a, 0x5b, 0x7b, 0x22, 0x70, 0x63, 0x22, 0x3a, 0x30, 0x2c, 0x22, 0x6f, 0x70, 0x22, 0x3a, 0x22, 0x50, 0x55, 0x53, 0x48, 0x31, 0x22, 0x2c, 0x22, 0x67, 0x61, 0x73, 0x22, 0x3a, 0x33, 0x30, 0x32, 0x39, 0x36, 0x2c, 0x22, 0x67, 0x61, 0x73, 0x43, 0x6f, 0x73, 0x74, 0x22, 0x3a, 0x33, 0x2c, 0x22, 0x64, 0x65, 0x70, 0x74, 0x68, 0x22, 0x3a, 0x31, 0x7d, 0x2c, 0x7b, 0x22, 0x70, 0x63, 0x22, 0x3a, 0x32, 0x2c, 0x22, 0x6f, 0x70, 0x22, 0x3a, 0x22, 0x50, 0x55, 0x53, 0x48, 0x31, 0x22, 0x2c, 0x22, 0x67, 0x61, 0x73, 0x22, 0x3a, 0x33, 0x30, 0x32, 0x39, 0x33, 0x2c, 0x22, 0x67},
dynamicTxFee: false, enableFeemarket: false,
}, },
{ {
msg: "javascript tracer", msg: "javascript tracer",
@ -646,7 +646,7 @@ func (suite *KeeperTestSuite) TestTraceTx() {
traceResponse: []byte{0x5b, 0x5d}, traceResponse: []byte{0x5b, 0x5d},
}, },
{ {
msg: "default trace with dynamicTxFee", msg: "default trace with enableFeemarket",
malleate: func() { malleate: func() {
txIndex = 0 txIndex = 0
traceConfig = &types.TraceConfig{ traceConfig = &types.TraceConfig{
@ -656,12 +656,12 @@ func (suite *KeeperTestSuite) TestTraceTx() {
} }
predecessors = []*types.MsgEthereumTx{} predecessors = []*types.MsgEthereumTx{}
}, },
expPass: true, expPass: true,
traceResponse: []byte{0x7b, 0x22, 0x67, 0x61, 0x73, 0x22, 0x3a, 0x33, 0x34, 0x38, 0x32, 0x38, 0x2c, 0x22, 0x66, 0x61, 0x69, 0x6c, 0x65, 0x64, 0x22, 0x3a, 0x66, 0x61, 0x6c, 0x73, 0x65, 0x2c, 0x22, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x22, 0x3a, 0x22, 0x22, 0x2c, 0x22, 0x73, 0x74, 0x72, 0x75, 0x63, 0x74, 0x4c, 0x6f, 0x67, 0x73, 0x22, 0x3a, 0x5b, 0x7b, 0x22, 0x70, 0x63, 0x22, 0x3a, 0x30, 0x2c, 0x22, 0x6f, 0x70, 0x22, 0x3a, 0x22, 0x50, 0x55, 0x53, 0x48, 0x31, 0x22, 0x2c, 0x22, 0x67, 0x61, 0x73, 0x22, 0x3a, 0x33, 0x30, 0x32, 0x39, 0x36, 0x2c, 0x22, 0x67, 0x61, 0x73, 0x43, 0x6f, 0x73, 0x74, 0x22, 0x3a, 0x33, 0x2c, 0x22, 0x64, 0x65, 0x70, 0x74, 0x68, 0x22, 0x3a, 0x31, 0x7d, 0x2c, 0x7b, 0x22, 0x70, 0x63, 0x22, 0x3a, 0x32, 0x2c, 0x22, 0x6f, 0x70, 0x22, 0x3a, 0x22, 0x50, 0x55, 0x53, 0x48, 0x31, 0x22, 0x2c, 0x22, 0x67, 0x61, 0x73, 0x22, 0x3a, 0x33, 0x30, 0x32, 0x39, 0x33, 0x2c, 0x22, 0x67}, traceResponse: []byte{0x7b, 0x22, 0x67, 0x61, 0x73, 0x22, 0x3a, 0x33, 0x34, 0x38, 0x32, 0x38, 0x2c, 0x22, 0x66, 0x61, 0x69, 0x6c, 0x65, 0x64, 0x22, 0x3a, 0x66, 0x61, 0x6c, 0x73, 0x65, 0x2c, 0x22, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x22, 0x3a, 0x22, 0x22, 0x2c, 0x22, 0x73, 0x74, 0x72, 0x75, 0x63, 0x74, 0x4c, 0x6f, 0x67, 0x73, 0x22, 0x3a, 0x5b, 0x7b, 0x22, 0x70, 0x63, 0x22, 0x3a, 0x30, 0x2c, 0x22, 0x6f, 0x70, 0x22, 0x3a, 0x22, 0x50, 0x55, 0x53, 0x48, 0x31, 0x22, 0x2c, 0x22, 0x67, 0x61, 0x73, 0x22, 0x3a, 0x33, 0x30, 0x32, 0x39, 0x36, 0x2c, 0x22, 0x67, 0x61, 0x73, 0x43, 0x6f, 0x73, 0x74, 0x22, 0x3a, 0x33, 0x2c, 0x22, 0x64, 0x65, 0x70, 0x74, 0x68, 0x22, 0x3a, 0x31, 0x7d, 0x2c, 0x7b, 0x22, 0x70, 0x63, 0x22, 0x3a, 0x32, 0x2c, 0x22, 0x6f, 0x70, 0x22, 0x3a, 0x22, 0x50, 0x55, 0x53, 0x48, 0x31, 0x22, 0x2c, 0x22, 0x67, 0x61, 0x73, 0x22, 0x3a, 0x33, 0x30, 0x32, 0x39, 0x33, 0x2c, 0x22, 0x67},
dynamicTxFee: true, enableFeemarket: true,
}, },
{ {
msg: "javascript tracer with dynamicTxFee", msg: "javascript tracer with enableFeemarket",
malleate: func() { malleate: func() {
txIndex = 0 txIndex = 0
traceConfig = &types.TraceConfig{ traceConfig = &types.TraceConfig{
@ -669,9 +669,9 @@ func (suite *KeeperTestSuite) TestTraceTx() {
} }
predecessors = []*types.MsgEthereumTx{} predecessors = []*types.MsgEthereumTx{}
}, },
expPass: true, expPass: true,
traceResponse: []byte{0x5b, 0x5d}, traceResponse: []byte{0x5b, 0x5d},
dynamicTxFee: true, enableFeemarket: true,
}, },
{ {
msg: "default tracer with predecessors", msg: "default tracer with predecessors",
@ -690,15 +690,15 @@ func (suite *KeeperTestSuite) TestTraceTx() {
predecessors = append(predecessors, firstTx) predecessors = append(predecessors, firstTx)
}, },
expPass: true, expPass: true,
traceResponse: []byte{0x7b, 0x22, 0x67, 0x61, 0x73, 0x22, 0x3a, 0x33, 0x34, 0x38, 0x32, 0x38, 0x2c, 0x22, 0x66, 0x61, 0x69, 0x6c, 0x65, 0x64, 0x22, 0x3a, 0x66, 0x61, 0x6c, 0x73, 0x65, 0x2c, 0x22, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x22, 0x3a, 0x22, 0x22, 0x2c, 0x22, 0x73, 0x74, 0x72, 0x75, 0x63, 0x74, 0x4c, 0x6f, 0x67, 0x73, 0x22, 0x3a, 0x5b, 0x7b, 0x22, 0x70, 0x63, 0x22, 0x3a, 0x30, 0x2c, 0x22, 0x6f, 0x70, 0x22, 0x3a, 0x22, 0x50, 0x55, 0x53, 0x48, 0x31, 0x22, 0x2c, 0x22, 0x67, 0x61, 0x73, 0x22, 0x3a, 0x31, 0x33, 0x31, 0x39, 0x36, 0x2c, 0x22, 0x67, 0x61, 0x73, 0x43, 0x6f, 0x73, 0x74, 0x22, 0x3a, 0x33, 0x2c, 0x22, 0x64, 0x65, 0x70, 0x74, 0x68, 0x22, 0x3a, 0x31, 0x2c, 0x22, 0x73, 0x74, 0x61, 0x63, 0x6b, 0x22, 0x3a, 0x5b, 0x5d, 0x7d, 0x2c, 0x7b, 0x22, 0x70, 0x63, 0x22, 0x3a, 0x32, 0x2c, 0x22, 0x6f, 0x70, 0x22, 0x3a, 0x22, 0x50, 0x55, 0x53, 0x48, 0x31, 0x22, 0x2c, 0x22, 0x67, 0x61}, traceResponse: []byte{0x7b, 0x22, 0x67, 0x61, 0x73, 0x22, 0x3a, 0x33, 0x34, 0x38, 0x32, 0x38, 0x2c, 0x22, 0x66, 0x61, 0x69, 0x6c, 0x65, 0x64, 0x22, 0x3a, 0x66, 0x61, 0x6c, 0x73, 0x65, 0x2c, 0x22, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x22, 0x3a, 0x22, 0x22, 0x2c, 0x22, 0x73, 0x74, 0x72, 0x75, 0x63, 0x74, 0x4c, 0x6f, 0x67, 0x73, 0x22, 0x3a, 0x5b, 0x7b, 0x22, 0x70, 0x63, 0x22, 0x3a, 0x30, 0x2c, 0x22, 0x6f, 0x70, 0x22, 0x3a, 0x22, 0x50, 0x55, 0x53, 0x48, 0x31, 0x22, 0x2c, 0x22, 0x67, 0x61, 0x73, 0x22, 0x3a, 0x31, 0x33, 0x31, 0x39, 0x36, 0x2c, 0x22, 0x67, 0x61, 0x73, 0x43, 0x6f, 0x73, 0x74, 0x22, 0x3a, 0x33, 0x2c, 0x22, 0x64, 0x65, 0x70, 0x74, 0x68, 0x22, 0x3a, 0x31, 0x2c, 0x22, 0x73, 0x74, 0x61, 0x63, 0x6b, 0x22, 0x3a, 0x5b, 0x5d, 0x7d, 0x2c, 0x7b, 0x22, 0x70, 0x63, 0x22, 0x3a, 0x32, 0x2c, 0x22, 0x6f, 0x70, 0x22, 0x3a, 0x22, 0x50, 0x55, 0x53, 0x48, 0x31, 0x22, 0x2c, 0x22, 0x67, 0x61},
dynamicTxFee: false, enableFeemarket: false,
}, },
} }
for _, tc := range testCases { for _, tc := range testCases {
suite.Run(fmt.Sprintf("Case %s", tc.msg), func() { suite.Run(fmt.Sprintf("Case %s", tc.msg), func() {
suite.dynamicTxFee = tc.dynamicTxFee suite.enableFeemarket = tc.enableFeemarket
suite.SetupTest() suite.SetupTest()
// Deploy contract // Deploy contract
contractAddr := suite.DeployTestContract(suite.T(), suite.address, sdk.NewIntWithDecimal(1000, 18).BigInt()) contractAddr := suite.DeployTestContract(suite.T(), suite.address, sdk.NewIntWithDecimal(1000, 18).BigInt())
@ -731,7 +731,7 @@ func (suite *KeeperTestSuite) TestTraceTx() {
}) })
} }
suite.dynamicTxFee = false // reset flag suite.enableFeemarket = false // reset flag
} }
func (suite *KeeperTestSuite) TestTraceBlock() { func (suite *KeeperTestSuite) TestTraceBlock() {
@ -741,11 +741,11 @@ func (suite *KeeperTestSuite) TestTraceBlock() {
) )
testCases := []struct { testCases := []struct {
msg string msg string
malleate func() malleate func()
expPass bool expPass bool
traceResponse []byte traceResponse []byte
dynamicTxFee bool enableFeemarket bool
}{ }{
{ {
msg: "default trace", msg: "default trace",
@ -778,7 +778,7 @@ func (suite *KeeperTestSuite) TestTraceBlock() {
traceResponse: []byte{0x5b, 0x7b, 0x22, 0x72, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x22, 0x3a, 0x5b, 0x5d, 0x7d, 0x5d}, traceResponse: []byte{0x5b, 0x7b, 0x22, 0x72, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x22, 0x3a, 0x5b, 0x5d, 0x7d, 0x5d},
}, },
{ {
msg: "default trace with dynamicTxFee and filtered return", msg: "default trace with enableFeemarket and filtered return",
malleate: func() { malleate: func() {
traceConfig = &types.TraceConfig{ traceConfig = &types.TraceConfig{
DisableStack: true, DisableStack: true,
@ -786,20 +786,20 @@ func (suite *KeeperTestSuite) TestTraceBlock() {
EnableMemory: false, EnableMemory: false,
} }
}, },
expPass: true, expPass: true,
traceResponse: []byte{0x5b, 0x7b, 0x22, 0x72, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x22, 0x3a, 0x7b, 0x22, 0x67, 0x61, 0x73, 0x22, 0x3a, 0x33, 0x34, 0x38, 0x32, 0x38, 0x2c, 0x22, 0x66, 0x61, 0x69, 0x6c, 0x65, 0x64, 0x22, 0x3a, 0x66, 0x61, 0x6c, 0x73, 0x65, 0x2c, 0x22, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x22, 0x3a, 0x22, 0x22, 0x2c, 0x22, 0x73, 0x74, 0x72, 0x75, 0x63, 0x74, 0x4c, 0x6f, 0x67, 0x73, 0x22, 0x3a, 0x5b, 0x7b, 0x22, 0x70, 0x63, 0x22, 0x3a, 0x30, 0x2c, 0x22, 0x6f, 0x70, 0x22, 0x3a, 0x22, 0x50, 0x55, 0x53, 0x48, 0x31, 0x22, 0x2c, 0x22, 0x67, 0x61, 0x73, 0x22, 0x3a, 0x33, 0x30, 0x32, 0x39, 0x36, 0x2c, 0x22, 0x67, 0x61, 0x73, 0x43, 0x6f, 0x73, 0x74, 0x22, 0x3a, 0x33, 0x2c, 0x22, 0x64, 0x65, 0x70, 0x74, 0x68, 0x22, 0x3a, 0x31, 0x7d, 0x2c, 0x7b, 0x22, 0x70, 0x63, 0x22, 0x3a, 0x32, 0x2c, 0x22, 0x6f, 0x70, 0x22, 0x3a, 0x22, 0x50, 0x55, 0x53, 0x48, 0x31, 0x22, 0x2c, 0x22, 0x67, 0x61}, traceResponse: []byte{0x5b, 0x7b, 0x22, 0x72, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x22, 0x3a, 0x7b, 0x22, 0x67, 0x61, 0x73, 0x22, 0x3a, 0x33, 0x34, 0x38, 0x32, 0x38, 0x2c, 0x22, 0x66, 0x61, 0x69, 0x6c, 0x65, 0x64, 0x22, 0x3a, 0x66, 0x61, 0x6c, 0x73, 0x65, 0x2c, 0x22, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x22, 0x3a, 0x22, 0x22, 0x2c, 0x22, 0x73, 0x74, 0x72, 0x75, 0x63, 0x74, 0x4c, 0x6f, 0x67, 0x73, 0x22, 0x3a, 0x5b, 0x7b, 0x22, 0x70, 0x63, 0x22, 0x3a, 0x30, 0x2c, 0x22, 0x6f, 0x70, 0x22, 0x3a, 0x22, 0x50, 0x55, 0x53, 0x48, 0x31, 0x22, 0x2c, 0x22, 0x67, 0x61, 0x73, 0x22, 0x3a, 0x33, 0x30, 0x32, 0x39, 0x36, 0x2c, 0x22, 0x67, 0x61, 0x73, 0x43, 0x6f, 0x73, 0x74, 0x22, 0x3a, 0x33, 0x2c, 0x22, 0x64, 0x65, 0x70, 0x74, 0x68, 0x22, 0x3a, 0x31, 0x7d, 0x2c, 0x7b, 0x22, 0x70, 0x63, 0x22, 0x3a, 0x32, 0x2c, 0x22, 0x6f, 0x70, 0x22, 0x3a, 0x22, 0x50, 0x55, 0x53, 0x48, 0x31, 0x22, 0x2c, 0x22, 0x67, 0x61},
dynamicTxFee: true, enableFeemarket: true,
}, },
{ {
msg: "javascript tracer with dynamicTxFee", msg: "javascript tracer with enableFeemarket",
malleate: func() { malleate: func() {
traceConfig = &types.TraceConfig{ traceConfig = &types.TraceConfig{
Tracer: "{data: [], fault: function(log) {}, step: function(log) { if(log.op.toString() == \"CALL\") this.data.push(log.stack.peek(0)); }, result: function() { return this.data; }}", Tracer: "{data: [], fault: function(log) {}, step: function(log) { if(log.op.toString() == \"CALL\") this.data.push(log.stack.peek(0)); }, result: function() { return this.data; }}",
} }
}, },
expPass: true, expPass: true,
traceResponse: []byte{0x5b, 0x7b, 0x22, 0x72, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x22, 0x3a, 0x5b, 0x5d, 0x7d, 0x5d}, traceResponse: []byte{0x5b, 0x7b, 0x22, 0x72, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x22, 0x3a, 0x5b, 0x5d, 0x7d, 0x5d},
dynamicTxFee: true, enableFeemarket: true,
}, },
{ {
msg: "tracer with multiple transactions", msg: "tracer with multiple transactions",
@ -816,16 +816,16 @@ func (suite *KeeperTestSuite) TestTraceBlock() {
// overwrite txs to include only the ones on new block // overwrite txs to include only the ones on new block
txs = append([]*types.MsgEthereumTx{}, firstTx, secondTx) txs = append([]*types.MsgEthereumTx{}, firstTx, secondTx)
}, },
expPass: true, expPass: true,
traceResponse: []byte{0x5b, 0x7b, 0x22, 0x72, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x22, 0x3a, 0x7b, 0x22, 0x67, 0x61, 0x73, 0x22, 0x3a, 0x33, 0x34, 0x38, 0x32, 0x38, 0x2c, 0x22, 0x66, 0x61, 0x69, 0x6c, 0x65, 0x64, 0x22, 0x3a, 0x66, 0x61, 0x6c, 0x73, 0x65, 0x2c, 0x22, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x22, 0x3a, 0x22, 0x22, 0x2c, 0x22, 0x73, 0x74, 0x72, 0x75, 0x63, 0x74, 0x4c, 0x6f, 0x67, 0x73, 0x22, 0x3a, 0x5b, 0x7b, 0x22, 0x70, 0x63, 0x22, 0x3a, 0x30, 0x2c, 0x22, 0x6f, 0x70, 0x22, 0x3a, 0x22, 0x50, 0x55, 0x53, 0x48, 0x31, 0x22, 0x2c, 0x22, 0x67, 0x61, 0x73, 0x22, 0x3a, 0x33, 0x30, 0x32, 0x39, 0x36, 0x2c, 0x22, 0x67, 0x61, 0x73, 0x43, 0x6f, 0x73, 0x74, 0x22, 0x3a, 0x33, 0x2c, 0x22, 0x64, 0x65, 0x70, 0x74, 0x68, 0x22, 0x3a, 0x31, 0x2c, 0x22, 0x73, 0x74, 0x61, 0x63, 0x6b, 0x22, 0x3a, 0x5b, 0x5d, 0x7d, 0x2c, 0x7b, 0x22, 0x70, 0x63, 0x22, 0x3a, 0x32, 0x2c, 0x22, 0x6f, 0x70, 0x22, 0x3a}, traceResponse: []byte{0x5b, 0x7b, 0x22, 0x72, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x22, 0x3a, 0x7b, 0x22, 0x67, 0x61, 0x73, 0x22, 0x3a, 0x33, 0x34, 0x38, 0x32, 0x38, 0x2c, 0x22, 0x66, 0x61, 0x69, 0x6c, 0x65, 0x64, 0x22, 0x3a, 0x66, 0x61, 0x6c, 0x73, 0x65, 0x2c, 0x22, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x22, 0x3a, 0x22, 0x22, 0x2c, 0x22, 0x73, 0x74, 0x72, 0x75, 0x63, 0x74, 0x4c, 0x6f, 0x67, 0x73, 0x22, 0x3a, 0x5b, 0x7b, 0x22, 0x70, 0x63, 0x22, 0x3a, 0x30, 0x2c, 0x22, 0x6f, 0x70, 0x22, 0x3a, 0x22, 0x50, 0x55, 0x53, 0x48, 0x31, 0x22, 0x2c, 0x22, 0x67, 0x61, 0x73, 0x22, 0x3a, 0x33, 0x30, 0x32, 0x39, 0x36, 0x2c, 0x22, 0x67, 0x61, 0x73, 0x43, 0x6f, 0x73, 0x74, 0x22, 0x3a, 0x33, 0x2c, 0x22, 0x64, 0x65, 0x70, 0x74, 0x68, 0x22, 0x3a, 0x31, 0x2c, 0x22, 0x73, 0x74, 0x61, 0x63, 0x6b, 0x22, 0x3a, 0x5b, 0x5d, 0x7d, 0x2c, 0x7b, 0x22, 0x70, 0x63, 0x22, 0x3a, 0x32, 0x2c, 0x22, 0x6f, 0x70, 0x22, 0x3a},
dynamicTxFee: false, enableFeemarket: false,
}, },
} }
for _, tc := range testCases { for _, tc := range testCases {
suite.Run(fmt.Sprintf("Case %s", tc.msg), func() { suite.Run(fmt.Sprintf("Case %s", tc.msg), func() {
txs = []*types.MsgEthereumTx{} txs = []*types.MsgEthereumTx{}
suite.dynamicTxFee = tc.dynamicTxFee suite.enableFeemarket = tc.enableFeemarket
suite.SetupTest() suite.SetupTest()
// Deploy contract // Deploy contract
contractAddr := suite.DeployTestContract(suite.T(), suite.address, sdk.NewIntWithDecimal(1000, 18).BigInt()) contractAddr := suite.DeployTestContract(suite.T(), suite.address, sdk.NewIntWithDecimal(1000, 18).BigInt())
@ -857,5 +857,5 @@ func (suite *KeeperTestSuite) TestTraceBlock() {
}) })
} }
suite.dynamicTxFee = false // reset flag suite.enableFeemarket = false // reset flag
} }

View File

@ -374,3 +374,19 @@ func (k *Keeper) PostTxProcessing(txHash common.Hash, logs []*ethtypes.Log) erro
func (k Keeper) Tracer(msg core.Message, ethCfg *params.ChainConfig) vm.Tracer { func (k Keeper) Tracer(msg core.Message, ethCfg *params.ChainConfig) vm.Tracer {
return types.NewTracer(k.tracer, msg, ethCfg, k.Ctx().BlockHeight()) return types.NewTracer(k.tracer, msg, ethCfg, k.Ctx().BlockHeight())
} }
// BaseFee returns current base fee, return values:
// - `nil`: london hardfork not enabled.
// - `0`: london hardfork enabled but feemarket is not enabled.
// - `n`: both london hardfork and feemarket are enabled.
func (k Keeper) BaseFee(ctx sdk.Context, ethCfg *params.ChainConfig) *big.Int {
if !types.IsLondon(ethCfg, ctx.BlockHeight()) {
return nil
}
baseFee := k.feeMarketKeeper.GetBaseFee(ctx)
if baseFee == nil {
// return 0 if feemarket not enabled.
baseFee = big.NewInt(0)
}
return baseFee
}

View File

@ -3,6 +3,7 @@ package keeper_test
import ( import (
_ "embed" _ "embed"
"encoding/json" "encoding/json"
"math"
"math/big" "math/big"
"testing" "testing"
"time" "time"
@ -61,7 +62,8 @@ type KeeperTestSuite struct {
appCodec codec.Codec appCodec codec.Codec
signer keyring.Signer signer keyring.Signer
dynamicTxFee bool enableFeemarket bool
enableLondonHF bool
mintFeeCollector bool mintFeeCollector bool
} }
@ -80,16 +82,22 @@ func (suite *KeeperTestSuite) DoSetupTest(t require.TestingT) {
require.NoError(t, err) require.NoError(t, err)
suite.consAddress = sdk.ConsAddress(priv.PubKey().Address()) suite.consAddress = sdk.ConsAddress(priv.PubKey().Address())
if suite.dynamicTxFee { suite.app = app.Setup(checkTx, func(app *app.EthermintApp, genesis simapp.GenesisState) simapp.GenesisState {
// setup feemarketGenesis params if suite.enableFeemarket {
feemarketGenesis := feemarkettypes.DefaultGenesisState() feemarketGenesis := feemarkettypes.DefaultGenesisState()
feemarketGenesis.Params.EnableHeight = 1 feemarketGenesis.Params.EnableHeight = 1
feemarketGenesis.Params.NoBaseFee = false feemarketGenesis.Params.NoBaseFee = false
feemarketGenesis.BaseFee = sdk.NewInt(feemarketGenesis.Params.InitialBaseFee) feemarketGenesis.BaseFee = sdk.NewInt(feemarketGenesis.Params.InitialBaseFee)
suite.app = app.Setup(checkTx, feemarketGenesis) genesis[feemarkettypes.ModuleName] = app.AppCodec().MustMarshalJSON(feemarketGenesis)
} else { }
suite.app = app.Setup(checkTx, nil) if !suite.enableLondonHF {
} evmGenesis := types.DefaultGenesisState()
maxInt := sdk.NewInt(math.MaxInt64)
evmGenesis.Params.ChainConfig.LondonBlock = &maxInt
genesis[types.ModuleName] = app.AppCodec().MustMarshalJSON(evmGenesis)
}
return genesis
})
if suite.mintFeeCollector { if suite.mintFeeCollector {
// mint some coin to fee collector // mint some coin to fee collector
@ -225,7 +233,7 @@ func (suite *KeeperTestSuite) DeployTestContract(t require.TestingT, owner commo
require.NoError(t, err) require.NoError(t, err)
var erc20DeployTx *types.MsgEthereumTx var erc20DeployTx *types.MsgEthereumTx
if suite.dynamicTxFee { if suite.enableFeemarket {
erc20DeployTx = types.NewTxContract( erc20DeployTx = types.NewTxContract(
chainID, chainID,
nonce, nonce,
@ -276,7 +284,7 @@ func (suite *KeeperTestSuite) TransferERC20Token(t require.TestingT, contractAdd
nonce := suite.app.EvmKeeper.GetNonce(suite.address) nonce := suite.app.EvmKeeper.GetNonce(suite.address)
var ercTransferTx *types.MsgEthereumTx var ercTransferTx *types.MsgEthereumTx
if suite.dynamicTxFee { if suite.enableFeemarket {
ercTransferTx = types.NewTx( ercTransferTx = types.NewTx(
chainID, chainID,
nonce, nonce,
@ -333,7 +341,7 @@ func (suite *KeeperTestSuite) DeployTestMessageCall(t require.TestingT) common.A
nonce := suite.app.EvmKeeper.GetNonce(suite.address) nonce := suite.app.EvmKeeper.GetNonce(suite.address)
var erc20DeployTx *types.MsgEthereumTx var erc20DeployTx *types.MsgEthereumTx
if suite.dynamicTxFee { if suite.enableFeemarket {
erc20DeployTx = types.NewTxContract( erc20DeployTx = types.NewTxContract(
chainID, chainID,
nonce, nonce,
@ -367,6 +375,38 @@ func (suite *KeeperTestSuite) DeployTestMessageCall(t require.TestingT) common.A
return crypto.CreateAddress(suite.address, nonce) return crypto.CreateAddress(suite.address, nonce)
} }
func TestKeeperTestSuite(t *testing.T) { func (suite *KeeperTestSuite) TestBaseFee() {
suite.Run(t, new(KeeperTestSuite)) testCases := []struct {
name string
enableLondonHF bool
enableFeemarket bool
expectBaseFee *big.Int
}{
{"not enable london HF, not enable feemarket", false, false, nil},
{"enable london HF, not enable feemarket", true, false, big.NewInt(0)},
{"enable london HF, enable feemarket", true, true, big.NewInt(1000000000)},
{"not enable london HF, enable feemarket", false, true, nil},
}
for _, tc := range testCases {
suite.Run(tc.name, func() {
suite.enableFeemarket = tc.enableFeemarket
suite.enableLondonHF = tc.enableLondonHF
suite.SetupTest()
suite.app.EvmKeeper.BeginBlock(suite.ctx, abci.RequestBeginBlock{})
params := suite.app.EvmKeeper.GetParams(suite.ctx)
ethCfg := params.ChainConfig.EthereumConfig(suite.app.EvmKeeper.ChainID())
baseFee := suite.app.EvmKeeper.BaseFee(suite.ctx, ethCfg)
suite.Require().Equal(tc.expectBaseFee, baseFee)
})
}
suite.enableFeemarket = false
suite.enableLondonHF = true
}
func TestKeeperTestSuite(t *testing.T) {
suite.Run(t, &KeeperTestSuite{
enableFeemarket: false,
enableLondonHF: true,
})
} }

View File

@ -31,11 +31,7 @@ func (k *Keeper) EVMConfig(ctx sdk.Context) (*types.EVMConfig, error) {
return nil, sdkerrors.Wrap(err, "failed to obtain coinbase address") return nil, sdkerrors.Wrap(err, "failed to obtain coinbase address")
} }
var baseFee *big.Int baseFee := k.BaseFee(ctx, ethCfg)
if types.IsLondon(ethCfg, ctx.BlockHeight()) {
baseFee = k.feeMarketKeeper.GetBaseFee(ctx)
}
return &types.EVMConfig{ return &types.EVMConfig{
Params: params, Params: params,
ChainConfig: ethCfg, ChainConfig: ethCfg,
@ -178,15 +174,9 @@ func (k *Keeper) ApplyTransaction(tx *ethtypes.Transaction) (*types.MsgEthereumT
return nil, sdkerrors.Wrap(err, "failed to load evm config") return nil, sdkerrors.Wrap(err, "failed to load evm config")
} }
// get the latest signer according to the chain rules from the config // get the signer according to the chain rules from the config and block height
signer := ethtypes.MakeSigner(cfg.ChainConfig, big.NewInt(ctx.BlockHeight())) signer := ethtypes.MakeSigner(cfg.ChainConfig, big.NewInt(ctx.BlockHeight()))
msg, err := tx.AsMessage(signer, cfg.BaseFee)
var baseFee *big.Int
if types.IsLondon(cfg.ChainConfig, ctx.BlockHeight()) {
baseFee = k.feeMarketKeeper.GetBaseFee(ctx)
}
msg, err := tx.AsMessage(signer, baseFee)
if err != nil { if err != nil {
return nil, sdkerrors.Wrap(err, "failed to return ethereum transaction as core message") return nil, sdkerrors.Wrap(err, "failed to return ethereum transaction as core message")
} }

View File

@ -142,7 +142,7 @@ func newNativeMessage(
} }
func BenchmarkApplyTransaction(b *testing.B) { func BenchmarkApplyTransaction(b *testing.B) {
suite := KeeperTestSuite{} suite := KeeperTestSuite{enableLondonHF: true}
suite.DoSetupTest(b) suite.DoSetupTest(b)
ethSigner := ethtypes.LatestSignerForChainID(suite.app.EvmKeeper.ChainID()) ethSigner := ethtypes.LatestSignerForChainID(suite.app.EvmKeeper.ChainID())
@ -169,7 +169,7 @@ func BenchmarkApplyTransaction(b *testing.B) {
} }
func BenchmarkApplyTransactionWithLegacyTx(b *testing.B) { func BenchmarkApplyTransactionWithLegacyTx(b *testing.B) {
suite := KeeperTestSuite{} suite := KeeperTestSuite{enableLondonHF: true}
suite.DoSetupTest(b) suite.DoSetupTest(b)
ethSigner := ethtypes.LatestSignerForChainID(suite.app.EvmKeeper.ChainID()) ethSigner := ethtypes.LatestSignerForChainID(suite.app.EvmKeeper.ChainID())
@ -196,7 +196,7 @@ func BenchmarkApplyTransactionWithLegacyTx(b *testing.B) {
} }
func BenchmarkApplyTransactionWithDynamicFeeTx(b *testing.B) { func BenchmarkApplyTransactionWithDynamicFeeTx(b *testing.B) {
suite := KeeperTestSuite{dynamicTxFee: true} suite := KeeperTestSuite{enableFeemarket: true, enableLondonHF: true}
suite.DoSetupTest(b) suite.DoSetupTest(b)
ethSigner := ethtypes.LatestSignerForChainID(suite.app.EvmKeeper.ChainID()) ethSigner := ethtypes.LatestSignerForChainID(suite.app.EvmKeeper.ChainID())
@ -223,7 +223,7 @@ func BenchmarkApplyTransactionWithDynamicFeeTx(b *testing.B) {
} }
func BenchmarkApplyMessage(b *testing.B) { func BenchmarkApplyMessage(b *testing.B) {
suite := KeeperTestSuite{} suite := KeeperTestSuite{enableLondonHF: true}
suite.DoSetupTest(b) suite.DoSetupTest(b)
params := suite.app.EvmKeeper.GetParams(suite.ctx) params := suite.app.EvmKeeper.GetParams(suite.ctx)
@ -258,7 +258,7 @@ func BenchmarkApplyMessage(b *testing.B) {
} }
func BenchmarkApplyMessageWithLegacyTx(b *testing.B) { func BenchmarkApplyMessageWithLegacyTx(b *testing.B) {
suite := KeeperTestSuite{} suite := KeeperTestSuite{enableLondonHF: true}
suite.DoSetupTest(b) suite.DoSetupTest(b)
params := suite.app.EvmKeeper.GetParams(suite.ctx) params := suite.app.EvmKeeper.GetParams(suite.ctx)
@ -293,7 +293,7 @@ func BenchmarkApplyMessageWithLegacyTx(b *testing.B) {
} }
func BenchmarkApplyMessageWithDynamicFeeTx(b *testing.B) { func BenchmarkApplyMessageWithDynamicFeeTx(b *testing.B) {
suite := KeeperTestSuite{dynamicTxFee: true} suite := KeeperTestSuite{enableFeemarket: true, enableLondonHF: true}
suite.DoSetupTest(b) suite.DoSetupTest(b)
params := suite.app.EvmKeeper.GetParams(suite.ctx) params := suite.app.EvmKeeper.GetParams(suite.ctx)

View File

@ -507,7 +507,8 @@ func (suite *KeeperTestSuite) TestEVMConfig() {
cfg, err := suite.app.EvmKeeper.EVMConfig(suite.ctx) cfg, err := suite.app.EvmKeeper.EVMConfig(suite.ctx)
suite.Require().NoError(err) suite.Require().NoError(err)
suite.Require().Equal(types.DefaultParams(), cfg.Params) suite.Require().Equal(types.DefaultParams(), cfg.Params)
suite.Require().Equal((*big.Int)(nil), cfg.BaseFee) // london hardfork is enabled by default
suite.Require().Equal(new(big.Int), cfg.BaseFee)
suite.Require().Equal(suite.address, cfg.CoinBase) suite.Require().Equal(suite.address, cfg.CoinBase)
suite.Require().Equal(types.DefaultParams().ChainConfig.EthereumConfig(big.NewInt(9000)), cfg.ChainConfig) suite.Require().Equal(types.DefaultParams().ChainConfig.EthereumConfig(big.NewInt(9000)), cfg.ChainConfig)
} }

View File

@ -20,17 +20,17 @@ func (suite *KeeperTestSuite) TestCheckSenderBalance() {
negInt := sdk.NewInt(-10) negInt := sdk.NewInt(-10)
testCases := []struct { testCases := []struct {
name string name string
to string to string
gasLimit uint64 gasLimit uint64
gasPrice *sdk.Int gasPrice *sdk.Int
gasFeeCap *big.Int gasFeeCap *big.Int
gasTipCap *big.Int gasTipCap *big.Int
cost *sdk.Int cost *sdk.Int
from string from string
accessList *ethtypes.AccessList accessList *ethtypes.AccessList
expectPass bool expectPass bool
dynamicTxFee bool enableFeemarket bool
}{ }{
{ {
name: "Enough balance", name: "Enough balance",
@ -113,92 +113,92 @@ func (suite *KeeperTestSuite) TestCheckSenderBalance() {
expectPass: false, expectPass: false,
}, },
{ {
name: "Enough balance w/ dynamicTxFee", name: "Enough balance w/ enableFeemarket",
to: suite.address.String(), to: suite.address.String(),
gasLimit: 10, gasLimit: 10,
gasFeeCap: big.NewInt(1), gasFeeCap: big.NewInt(1),
cost: &oneInt, cost: &oneInt,
from: suite.address.String(), from: suite.address.String(),
accessList: &ethtypes.AccessList{}, accessList: &ethtypes.AccessList{},
expectPass: true, expectPass: true,
dynamicTxFee: true, enableFeemarket: true,
}, },
{ {
name: "Equal balance w/ dynamicTxFee", name: "Equal balance w/ enableFeemarket",
to: suite.address.String(), to: suite.address.String(),
gasLimit: 99, gasLimit: 99,
gasFeeCap: big.NewInt(1), gasFeeCap: big.NewInt(1),
cost: &oneInt, cost: &oneInt,
from: suite.address.String(), from: suite.address.String(),
accessList: &ethtypes.AccessList{}, accessList: &ethtypes.AccessList{},
expectPass: true, expectPass: true,
dynamicTxFee: true, enableFeemarket: true,
}, },
{ {
name: "negative cost w/ dynamicTxFee", name: "negative cost w/ enableFeemarket",
to: suite.address.String(), to: suite.address.String(),
gasLimit: 1, gasLimit: 1,
gasFeeCap: big.NewInt(1), gasFeeCap: big.NewInt(1),
cost: &negInt, cost: &negInt,
from: suite.address.String(), from: suite.address.String(),
accessList: &ethtypes.AccessList{}, accessList: &ethtypes.AccessList{},
expectPass: false, expectPass: false,
dynamicTxFee: true, enableFeemarket: true,
}, },
{ {
name: "Higher gas limit, not enough balance w/ dynamicTxFee", name: "Higher gas limit, not enough balance w/ enableFeemarket",
to: suite.address.String(), to: suite.address.String(),
gasLimit: 100, gasLimit: 100,
gasFeeCap: big.NewInt(1), gasFeeCap: big.NewInt(1),
cost: &oneInt, cost: &oneInt,
from: suite.address.String(), from: suite.address.String(),
accessList: &ethtypes.AccessList{}, accessList: &ethtypes.AccessList{},
expectPass: false, expectPass: false,
dynamicTxFee: true, enableFeemarket: true,
}, },
{ {
name: "Higher gas price, enough balance w/ dynamicTxFee", name: "Higher gas price, enough balance w/ enableFeemarket",
to: suite.address.String(), to: suite.address.String(),
gasLimit: 10, gasLimit: 10,
gasFeeCap: big.NewInt(5), gasFeeCap: big.NewInt(5),
cost: &oneInt, cost: &oneInt,
from: suite.address.String(), from: suite.address.String(),
accessList: &ethtypes.AccessList{}, accessList: &ethtypes.AccessList{},
expectPass: true, expectPass: true,
dynamicTxFee: true, enableFeemarket: true,
}, },
{ {
name: "Higher gas price, not enough balance w/ dynamicTxFee", name: "Higher gas price, not enough balance w/ enableFeemarket",
to: suite.address.String(), to: suite.address.String(),
gasLimit: 20, gasLimit: 20,
gasFeeCap: big.NewInt(5), gasFeeCap: big.NewInt(5),
cost: &oneInt, cost: &oneInt,
from: suite.address.String(), from: suite.address.String(),
accessList: &ethtypes.AccessList{}, accessList: &ethtypes.AccessList{},
expectPass: false, expectPass: false,
dynamicTxFee: true, enableFeemarket: true,
}, },
{ {
name: "Higher cost, enough balance w/ dynamicTxFee", name: "Higher cost, enough balance w/ enableFeemarket",
to: suite.address.String(), to: suite.address.String(),
gasLimit: 10, gasLimit: 10,
gasFeeCap: big.NewInt(5), gasFeeCap: big.NewInt(5),
cost: &fiftyInt, cost: &fiftyInt,
from: suite.address.String(), from: suite.address.String(),
accessList: &ethtypes.AccessList{}, accessList: &ethtypes.AccessList{},
expectPass: true, expectPass: true,
dynamicTxFee: true, enableFeemarket: true,
}, },
{ {
name: "Higher cost, not enough balance w/ dynamicTxFee", name: "Higher cost, not enough balance w/ enableFeemarket",
to: suite.address.String(), to: suite.address.String(),
gasLimit: 10, gasLimit: 10,
gasFeeCap: big.NewInt(5), gasFeeCap: big.NewInt(5),
cost: &hundredInt, cost: &hundredInt,
from: suite.address.String(), from: suite.address.String(),
accessList: &ethtypes.AccessList{}, accessList: &ethtypes.AccessList{},
expectPass: false, expectPass: false,
dynamicTxFee: true, enableFeemarket: true,
}, },
} }
@ -215,7 +215,7 @@ func (suite *KeeperTestSuite) TestCheckSenderBalance() {
amount = tc.cost.BigInt() amount = tc.cost.BigInt()
} }
if tc.dynamicTxFee { if tc.enableFeemarket {
gasFeeCap = tc.gasFeeCap gasFeeCap = tc.gasFeeCap
if tc.gasTipCap == nil { if tc.gasTipCap == nil {
gasTipCap = oneInt.BigInt() gasTipCap = oneInt.BigInt()
@ -261,15 +261,15 @@ func (suite *KeeperTestSuite) TestDeductTxCostsFromUserBalance() {
initBalance := sdk.NewInt((ethparams.InitialBaseFee + 10) * 105) initBalance := sdk.NewInt((ethparams.InitialBaseFee + 10) * 105)
testCases := []struct { testCases := []struct {
name string name string
gasLimit uint64 gasLimit uint64
gasPrice *sdk.Int gasPrice *sdk.Int
gasFeeCap *big.Int gasFeeCap *big.Int
gasTipCap *big.Int gasTipCap *big.Int
cost *sdk.Int cost *sdk.Int
accessList *ethtypes.AccessList accessList *ethtypes.AccessList
expectPass bool expectPass bool
dynamicTxFee bool enableFeemarket bool
}{ }{
{ {
name: "Enough balance", name: "Enough balance",
@ -321,51 +321,51 @@ func (suite *KeeperTestSuite) TestDeductTxCostsFromUserBalance() {
accessList: &ethtypes.AccessList{}, accessList: &ethtypes.AccessList{},
expectPass: true, expectPass: true,
}, },
// testcases with dynamicTxFee enabled. // testcases with enableFeemarket enabled.
{ {
name: "Invalid gasFeeCap w/ dynamicTxFee", name: "Invalid gasFeeCap w/ enableFeemarket",
gasLimit: 10, gasLimit: 10,
gasFeeCap: big.NewInt(1), gasFeeCap: big.NewInt(1),
gasTipCap: big.NewInt(1), gasTipCap: big.NewInt(1),
cost: &oneInt, cost: &oneInt,
accessList: &ethtypes.AccessList{}, accessList: &ethtypes.AccessList{},
expectPass: false, expectPass: false,
dynamicTxFee: true, enableFeemarket: true,
}, },
{ {
name: "empty tip fee is valid to deduct", name: "empty tip fee is valid to deduct",
gasLimit: 10, gasLimit: 10,
gasFeeCap: big.NewInt(ethparams.InitialBaseFee), gasFeeCap: big.NewInt(ethparams.InitialBaseFee),
gasTipCap: big.NewInt(1), gasTipCap: big.NewInt(1),
cost: &oneInt, cost: &oneInt,
accessList: &ethtypes.AccessList{}, accessList: &ethtypes.AccessList{},
expectPass: true, expectPass: true,
dynamicTxFee: true, enableFeemarket: true,
}, },
{ {
name: "effectiveTip equal to gasTipCap", name: "effectiveTip equal to gasTipCap",
gasLimit: 100, gasLimit: 100,
gasFeeCap: big.NewInt(ethparams.InitialBaseFee + 2), gasFeeCap: big.NewInt(ethparams.InitialBaseFee + 2),
cost: &oneInt, cost: &oneInt,
accessList: &ethtypes.AccessList{}, accessList: &ethtypes.AccessList{},
expectPass: true, expectPass: true,
dynamicTxFee: true, enableFeemarket: true,
}, },
{ {
name: "effectiveTip equal to (gasFeeCap - baseFee)", name: "effectiveTip equal to (gasFeeCap - baseFee)",
gasLimit: 105, gasLimit: 105,
gasFeeCap: big.NewInt(ethparams.InitialBaseFee + 1), gasFeeCap: big.NewInt(ethparams.InitialBaseFee + 1),
gasTipCap: big.NewInt(2), gasTipCap: big.NewInt(2),
cost: &oneInt, cost: &oneInt,
accessList: &ethtypes.AccessList{}, accessList: &ethtypes.AccessList{},
expectPass: true, expectPass: true,
dynamicTxFee: true, enableFeemarket: true,
}, },
} }
for i, tc := range testCases { for i, tc := range testCases {
suite.Run(tc.name, func() { suite.Run(tc.name, func() {
suite.dynamicTxFee = tc.dynamicTxFee suite.enableFeemarket = tc.enableFeemarket
suite.SetupTest() suite.SetupTest()
var amount, gasPrice, gasFeeCap, gasTipCap *big.Int var amount, gasPrice, gasFeeCap, gasTipCap *big.Int
@ -373,7 +373,7 @@ func (suite *KeeperTestSuite) TestDeductTxCostsFromUserBalance() {
amount = tc.cost.BigInt() amount = tc.cost.BigInt()
} }
if suite.dynamicTxFee { if suite.enableFeemarket {
if tc.gasFeeCap != nil { if tc.gasFeeCap != nil {
gasFeeCap = tc.gasFeeCap gasFeeCap = tc.gasFeeCap
} }
@ -407,12 +407,12 @@ func (suite *KeeperTestSuite) TestDeductTxCostsFromUserBalance() {
evmtypes.DefaultEVMDenom, evmtypes.DefaultEVMDenom,
false, false,
false, false,
suite.dynamicTxFee, // london suite.enableFeemarket, // london
) )
if tc.expectPass { if tc.expectPass {
suite.Require().NoError(err, "valid test %d failed", i) suite.Require().NoError(err, "valid test %d failed", i)
if tc.dynamicTxFee { if tc.enableFeemarket {
baseFee := suite.app.FeeMarketKeeper.GetBaseFee(suite.ctx) baseFee := suite.app.FeeMarketKeeper.GetBaseFee(suite.ctx)
suite.Require().Equal( suite.Require().Equal(
fees, fees,
@ -436,5 +436,5 @@ func (suite *KeeperTestSuite) TestDeductTxCostsFromUserBalance() {
} }
}) })
} }
suite.dynamicTxFee = false // reset flag suite.enableFeemarket = false // reset flag
} }

View File

@ -136,7 +136,7 @@ func validateChainConfig(i interface{}) error {
return cfg.Validate() return cfg.Validate()
} }
// IsLondon returns if london hardfork is enabled.
func IsLondon(ethConfig *params.ChainConfig, height int64) bool { func IsLondon(ethConfig *params.ChainConfig, height int64) bool {
rules := ethConfig.Rules(big.NewInt(height)) return ethConfig.IsLondon(big.NewInt(height))
return rules.IsLondon
} }

View File

@ -71,7 +71,8 @@ func (k Keeper) SetBlockGasUsed(ctx sdk.Context, gas uint64) {
// Required by EIP1559 base fee calculation. // Required by EIP1559 base fee calculation.
// ---------------------------------------------------------------------------- // ----------------------------------------------------------------------------
// GetLastBaseFee returns the last base fee value from the store. // GetBaseFee returns the last base fee value from the store.
// returns nil if base fee is not enabled.
func (k Keeper) GetBaseFee(ctx sdk.Context) *big.Int { func (k Keeper) GetBaseFee(ctx sdk.Context) *big.Int {
store := ctx.KVStore(k.storeKey) store := ctx.KVStore(k.storeKey)
bz := store.Get(types.KeyPrefixBaseFee) bz := store.Get(types.KeyPrefixBaseFee)