From 8b679d7ffad0a2db7b357d954b43f6bc79aca117 Mon Sep 17 00:00:00 2001 From: Jeremy Wei Date: Wed, 8 Jan 2025 09:18:22 -0500 Subject: [PATCH] Fix: Base Fee Off By One (#2015) * checkpoint * add migration handler and test * add impl and fixed existing tests * add integration test * cleanup * more cleanup * prev base fee per gas avoids returning nil to avoid method handler crashed on replay * remove unused prefix * fix test * reserve storage slot 0 * fix * set new names and register migration handler * fix --- aclmapping/evm/mappings_test.go | 2 +- contracts/src/EVMCompatibilityTester.sol | 21 +++++++-- contracts/test/EVMCompatabilityTest.js | 41 ++++++++++++++++- evmrpc/block.go | 2 +- evmrpc/info.go | 4 +- evmrpc/simulate.go | 2 +- x/evm/ante/fee.go | 2 +- x/evm/keeper/evm_test.go | 6 +-- x/evm/keeper/fee.go | 45 +++++++++++++++---- x/evm/keeper/fee_test.go | 38 +++++++++++----- x/evm/keeper/keeper.go | 2 +- x/evm/keeper/params_test.go | 2 +- .../migrations/migrate_base_fee_off_by_one.go | 12 +++++ .../migrate_base_fee_off_by_one_test.go | 22 +++++++++ x/evm/module.go | 6 ++- x/evm/module_test.go | 2 +- x/evm/types/keys.go | 1 + 17 files changed, 174 insertions(+), 36 deletions(-) create mode 100644 x/evm/migrations/migrate_base_fee_off_by_one.go create mode 100644 x/evm/migrations/migrate_base_fee_off_by_one_test.go diff --git a/aclmapping/evm/mappings_test.go b/aclmapping/evm/mappings_test.go index 3974312066..1142499ce0 100644 --- a/aclmapping/evm/mappings_test.go +++ b/aclmapping/evm/mappings_test.go @@ -126,7 +126,7 @@ func (suite *KeeperTestSuite) TestMsgEVMTransaction() { ctx, err := suite.preprocessor.AnteHandle(handlerCtx, tx.GetTx(), false, func(ctx sdk.Context, _ sdk.Tx, _ bool) (sdk.Context, error) { return ctx, nil }) suite.Require().Nil(err) cms.ResetEvents() - suite.App.EvmKeeper.SetDynamicBaseFeePerGas(ctx, sdk.ZeroDec()) + suite.App.EvmKeeper.SetCurrBaseFeePerGas(ctx, sdk.ZeroDec()) _, err = suite.msgServer.EVMTransaction(sdk.WrapSDKContext(ctx), tc.msg) suite.Require().Nil(err) diff --git a/contracts/src/EVMCompatibilityTester.sol b/contracts/src/EVMCompatibilityTester.sol index 6c2ef83852..7f32b7440f 100644 --- a/contracts/src/EVMCompatibilityTester.sol +++ b/contracts/src/EVMCompatibilityTester.sol @@ -15,6 +15,9 @@ contract EVMCompatibilityTester { event StringSet(address indexed performer, string value); event LogIndexEvent(address indexed performer, uint256 value); event BytesSet(address indexed performer, bytes value); + // Example of contract storing and retrieving data + uint256 private storedData; // needs to be first storage variable + mapping(uint256 => uint256) public gasGuzzler; struct MsgDetails { address sender; @@ -23,9 +26,6 @@ contract EVMCompatibilityTester { uint256 gas; } - // Example of contract storing and retrieving data - uint256 private storedData; - // deployer of the contract address public owner; @@ -180,5 +180,20 @@ contract EVMCompatibilityTester { } return fee; } + + // useGas will at least use gasToUse amount of gas + function useGas(uint256 gasToUse) public { + // while gasleft() > gasUse, use use storage to use gas + uint256 counter = 0; + uint256 startGas = gasleft(); + uint256 gasUsed = 0; + while (gasUsed < gasToUse) { + uint256 randomNumber = uint256(keccak256(abi.encodePacked(block.number, block.prevrandao, counter))); + counter++; + gasGuzzler[randomNumber] = randomNumber; + uint256 endGas = gasleft(); + gasUsed = startGas - endGas; + } + } } diff --git a/contracts/test/EVMCompatabilityTest.js b/contracts/test/EVMCompatabilityTest.js index 37a9ae2f1d..daf19a6193 100644 --- a/contracts/test/EVMCompatabilityTest.js +++ b/contracts/test/EVMCompatabilityTest.js @@ -312,7 +312,6 @@ describe("EVM Test", function () { expect(found).to.be.true; }); - it("Should set the string correctly and emit an event", async function () { await delay() const txResponse = await evmTester.setStringVar("test", { gasPrice: ethers.parseUnits('100', 'gwei') }); @@ -499,6 +498,7 @@ describe("EVM Test", function () { const zero = ethers.parseUnits('0', 'ether') const highgp = ethers.parseUnits("400", "gwei"); const gp = ethers.parseUnits("100", "gwei"); + const oneGwei = ethers.parseUnits("1", "gwei"); const testCases = [ ["No truncation from max priority fee", gp, gp], @@ -506,6 +506,45 @@ describe("EVM Test", function () { ["With complete truncation from max priority fee", zero, highgp] ]; + it("Check base fee on the right block", async function () { + await delay() + // check if base fee is 1gwei, otherwise wait + let iterations = 0 + while (true) { + const block = await ethers.provider.getBlock("latest"); + const baseFee = Number(block.baseFeePerGas); + if (baseFee === Number(oneGwei)) { + break; + } + iterations += 1 + if(iterations > 10) { + throw new Error("base fee hasn't dropped to 1gwei in 10 iterations") + } + await sleep(1000); + } + // use at least 1000000 gas to increase base fee + const txResponse = await evmTester.useGas(1000000, { gasPrice: ethers.parseUnits('100', 'gwei') }); + const receipt = await txResponse.wait(); + const blockHeight = receipt.blockNumber; + + // make sure block base fee is 1gwei and the block after + // has a base fee higher than 1gwei + const block = await ethers.provider.getBlock(blockHeight); + const baseFee = Number(block.baseFeePerGas); + expect(baseFee).to.equal(oneGwei); + // wait for the next block + while (true) { + const bn = await ethers.provider.getBlockNumber(); + if(bn !== blockHeight){ + break + } + await sleep(500) + } + const nextBlock = await ethers.provider.getBlock(blockHeight + 1); + const nextBaseFee = Number(nextBlock.baseFeePerGas); + expect(nextBaseFee).to.be.greaterThan(oneGwei); + }); + it("Should be able to send many EIP-1559 txs", async function () { const gp = ethers.parseUnits("100", "gwei"); const zero = ethers.parseUnits('0', 'ether') diff --git a/evmrpc/block.go b/evmrpc/block.go index 54a11fb447..28fceae322 100644 --- a/evmrpc/block.go +++ b/evmrpc/block.go @@ -277,7 +277,7 @@ func EncodeTmBlock( txHash := common.HexToHash(block.Block.DataHash.String()) resultHash := common.HexToHash(block.Block.LastResultsHash.String()) miner := common.HexToAddress(block.Block.ProposerAddress.String()) - baseFeePerGas := k.GetDynamicBaseFeePerGas(ctx).TruncateInt().BigInt() + baseFeePerGas := k.GetCurrBaseFeePerGas(ctx).TruncateInt().BigInt() var blockGasUsed int64 chainConfig := types.DefaultChainConfig().EthereumConfig(k.ChainID(ctx)) transactions := []interface{}{} diff --git a/evmrpc/info.go b/evmrpc/info.go index 3f7e4f1870..f5d345f6d4 100644 --- a/evmrpc/info.go +++ b/evmrpc/info.go @@ -76,7 +76,7 @@ func (i *InfoAPI) Accounts() (result []common.Address, returnErr error) { func (i *InfoAPI) GasPrice(ctx context.Context) (result *hexutil.Big, returnErr error) { startTime := time.Now() defer recordMetrics("eth_GasPrice", i.connectionType, startTime, returnErr == nil) - baseFee := i.keeper.GetDynamicBaseFeePerGas(i.ctxProvider(LatestCtxHeight)).TruncateInt().BigInt() + baseFee := i.keeper.GetCurrBaseFeePerGas(i.ctxProvider(LatestCtxHeight)).TruncateInt().BigInt() totalGasUsed, err := i.getCongestionData(ctx, nil) if err != nil { return nil, err @@ -229,7 +229,7 @@ func (i *InfoAPI) safeGetBaseFee(targetHeight int64) (res *big.Int) { res = nil } }() - baseFee := i.keeper.GetDynamicBaseFeePerGas(i.ctxProvider(targetHeight)) + baseFee := i.keeper.GetCurrBaseFeePerGas(i.ctxProvider(targetHeight)) res = baseFee.TruncateInt().BigInt() return } diff --git a/evmrpc/simulate.go b/evmrpc/simulate.go index a552771ac3..68775aa60a 100644 --- a/evmrpc/simulate.go +++ b/evmrpc/simulate.go @@ -436,7 +436,7 @@ func (b *Backend) getHeader(blockNumber *big.Int) *ethtypes.Header { header := ðtypes.Header{ Difficulty: common.Big0, Number: blockNumber, - BaseFee: b.keeper.GetDynamicBaseFeePerGas(b.ctxProvider(LatestCtxHeight)).TruncateInt().BigInt(), + BaseFee: b.keeper.GetCurrBaseFeePerGas(b.ctxProvider(LatestCtxHeight)).TruncateInt().BigInt(), GasLimit: b.config.GasCap, Time: uint64(time.Now().Unix()), ExcessBlobGas: &zeroExcessBlobGas, diff --git a/x/evm/ante/fee.go b/x/evm/ante/fee.go index b85edc2b15..d152e95be4 100644 --- a/x/evm/ante/fee.go +++ b/x/evm/ante/fee.go @@ -104,7 +104,7 @@ func (fc EVMFeeCheckDecorator) AnteHandle(ctx sdk.Context, tx sdk.Tx, simulate b // minimum fee per gas required for a tx to be processed func (fc EVMFeeCheckDecorator) getBaseFee(ctx sdk.Context) *big.Int { - return fc.evmKeeper.GetDynamicBaseFeePerGas(ctx).TruncateInt().BigInt() + return fc.evmKeeper.GetCurrBaseFeePerGas(ctx).TruncateInt().BigInt() } // lowest allowed fee per gas, base fee will not be lower than this diff --git a/x/evm/keeper/evm_test.go b/x/evm/keeper/evm_test.go index 3d4a0162b7..e71ae46dd3 100644 --- a/x/evm/keeper/evm_test.go +++ b/x/evm/keeper/evm_test.go @@ -39,15 +39,15 @@ func TestInternalCallCreateContract(t *testing.T) { _, err = k.HandleInternalEVMCall(ctx, req) require.Equal(t, "sei does not support EVM->CW->EVM call pattern", err.Error()) ctx = ctx.WithIsEVM(false) - oldBaseFee := k.GetDynamicBaseFeePerGas(ctx) - k.SetDynamicBaseFeePerGas(ctx, sdk.ZeroDec()) + oldBaseFee := k.GetCurrBaseFeePerGas(ctx) + k.SetCurrBaseFeePerGas(ctx, sdk.ZeroDec()) _, err = k.HandleInternalEVMCall(ctx, req) require.Nil(t, err) receipt, err := k.GetTransientReceipt(ctx, [32]byte{1, 2, 3}) require.Nil(t, err) require.NotNil(t, receipt) // reset base fee - k.SetDynamicBaseFeePerGas(ctx, oldBaseFee) + k.SetCurrBaseFeePerGas(ctx, oldBaseFee) } func TestInternalCall(t *testing.T) { diff --git a/x/evm/keeper/fee.go b/x/evm/keeper/fee.go index 4695b18685..251e8f3287 100644 --- a/x/evm/keeper/fee.go +++ b/x/evm/keeper/fee.go @@ -10,10 +10,12 @@ func (k *Keeper) AdjustDynamicBaseFeePerGas(ctx sdk.Context, blockGasUsed uint64 if ctx.ConsensusParams() == nil || ctx.ConsensusParams().Block == nil { return nil } - currentBaseFee := k.GetDynamicBaseFeePerGas(ctx) + prevBaseFee := k.GetNextBaseFeePerGas(ctx) + // set the resulting base fee for block n-1 on block n + k.SetCurrBaseFeePerGas(ctx, prevBaseFee) targetGasUsed := sdk.NewDec(int64(k.GetTargetGasUsedPerBlock(ctx))) - if targetGasUsed.IsZero() { - return ¤tBaseFee + if targetGasUsed.IsZero() { // avoid division by zero + return &prevBaseFee // return the previous base fee as is } minimumFeePerGas := k.GetParams(ctx).MinimumFeePerGas maximumFeePerGas := k.GetParams(ctx).MaximumFeePerGas @@ -32,14 +34,14 @@ func (k *Keeper) AdjustDynamicBaseFeePerGas(ctx sdk.Context, blockGasUsed uint64 denominator := blockGasLimit.Sub(targetGasUsed) percentageFull := numerator.Quo(denominator) adjustmentFactor := k.GetMaxDynamicBaseFeeUpwardAdjustment(ctx).Mul(percentageFull) - newBaseFee = currentBaseFee.Mul(sdk.NewDec(1).Add(adjustmentFactor)) + newBaseFee = prevBaseFee.Mul(sdk.NewDec(1).Add(adjustmentFactor)) } else { // downward adjustment numerator := targetGasUsed.Sub(blockGasUsedDec) denominator := targetGasUsed percentageEmpty := numerator.Quo(denominator) adjustmentFactor := k.GetMaxDynamicBaseFeeDownwardAdjustment(ctx).Mul(percentageEmpty) - newBaseFee = currentBaseFee.Mul(sdk.NewDec(1).Sub(adjustmentFactor)) + newBaseFee = prevBaseFee.Mul(sdk.NewDec(1).Sub(adjustmentFactor)) } // Ensure the new base fee is not lower than the minimum fee @@ -53,13 +55,13 @@ func (k *Keeper) AdjustDynamicBaseFeePerGas(ctx sdk.Context, blockGasUsed uint64 } // Set the new base fee for the next height - k.SetDynamicBaseFeePerGas(ctx.WithBlockHeight(ctx.BlockHeight()+1), newBaseFee) + k.SetNextBaseFeePerGas(ctx, newBaseFee) return &newBaseFee } // dont have height be a prefix, just store the current base fee directly -func (k *Keeper) GetDynamicBaseFeePerGas(ctx sdk.Context) sdk.Dec { +func (k *Keeper) GetCurrBaseFeePerGas(ctx sdk.Context) sdk.Dec { store := ctx.KVStore(k.storeKey) bz := store.Get(types.BaseFeePerGasPrefix) if bz == nil { @@ -77,7 +79,7 @@ func (k *Keeper) GetDynamicBaseFeePerGas(ctx sdk.Context) sdk.Dec { return d } -func (k *Keeper) SetDynamicBaseFeePerGas(ctx sdk.Context, baseFeePerGas sdk.Dec) { +func (k *Keeper) SetCurrBaseFeePerGas(ctx sdk.Context, baseFeePerGas sdk.Dec) { store := ctx.KVStore(k.storeKey) bz, err := baseFeePerGas.MarshalJSON() if err != nil { @@ -85,3 +87,30 @@ func (k *Keeper) SetDynamicBaseFeePerGas(ctx sdk.Context, baseFeePerGas sdk.Dec) } store.Set(types.BaseFeePerGasPrefix, bz) } + +func (k *Keeper) SetNextBaseFeePerGas(ctx sdk.Context, baseFeePerGas sdk.Dec) { + store := ctx.KVStore(k.storeKey) + bz, err := baseFeePerGas.MarshalJSON() + if err != nil { + panic(err) + } + store.Set(types.NextBaseFeePerGasPrefix, bz) +} + +func (k *Keeper) GetNextBaseFeePerGas(ctx sdk.Context) sdk.Dec { + store := ctx.KVStore(k.storeKey) + bz := store.Get(types.NextBaseFeePerGasPrefix) + if bz == nil { + minFeePerGas := k.GetMinimumFeePerGas(ctx) + if minFeePerGas.IsNil() { + minFeePerGas = types.DefaultParams().MinimumFeePerGas + } + return minFeePerGas + } + d := sdk.Dec{} + err := d.UnmarshalJSON(bz) + if err != nil { + panic(err) + } + return d +} diff --git a/x/evm/keeper/fee_test.go b/x/evm/keeper/fee_test.go index a4088fbed0..661620a40c 100644 --- a/x/evm/keeper/fee_test.go +++ b/x/evm/keeper/fee_test.go @@ -13,12 +13,12 @@ import ( func TestBaseFeePerGas(t *testing.T) { k := &testkeeper.EVMTestApp.EvmKeeper ctx := testkeeper.EVMTestApp.GetContextForDeliverTx([]byte{}) - require.Equal(t, k.GetMinimumFeePerGas(ctx), k.GetDynamicBaseFeePerGas(ctx)) - require.True(t, k.GetDynamicBaseFeePerGas(ctx).LTE(k.GetMaximumFeePerGas(ctx))) - originalbf := k.GetDynamicBaseFeePerGas(ctx) - k.SetDynamicBaseFeePerGas(ctx, sdk.OneDec()) - require.Equal(t, sdk.NewDecFromInt(sdk.NewInt(1)), k.GetDynamicBaseFeePerGas(ctx)) - k.SetDynamicBaseFeePerGas(ctx, originalbf) + require.Equal(t, k.GetMinimumFeePerGas(ctx), k.GetCurrBaseFeePerGas(ctx)) + require.True(t, k.GetCurrBaseFeePerGas(ctx).LTE(k.GetMaximumFeePerGas(ctx))) + originalbf := k.GetCurrBaseFeePerGas(ctx) + k.SetCurrBaseFeePerGas(ctx, sdk.OneDec()) + require.Equal(t, sdk.NewDecFromInt(sdk.NewInt(1)), k.GetCurrBaseFeePerGas(ctx)) + k.SetCurrBaseFeePerGas(ctx, originalbf) } func TestAdjustBaseFeePerGas(t *testing.T) { @@ -163,7 +163,7 @@ func TestAdjustBaseFeePerGas(t *testing.T) { ctx = ctx.WithConsensusParams(&tmproto.ConsensusParams{ Block: &tmproto.BlockParams{MaxGas: int64(tc.blockGasLimit)}, }) - k.SetDynamicBaseFeePerGas(ctx, sdk.NewDecFromInt(sdk.NewInt(int64(tc.currentBaseFee)))) + k.SetNextBaseFeePerGas(ctx, sdk.NewDecFromInt(sdk.NewInt(int64(tc.currentBaseFee)))) p := k.GetParams(ctx) p.MinimumFeePerGas = sdk.NewDec(int64(tc.minimumFee)) p.MaximumFeePerGas = sdk.NewDec(int64(tc.maximumFee)) @@ -174,7 +174,10 @@ func TestAdjustBaseFeePerGas(t *testing.T) { k.AdjustDynamicBaseFeePerGas(ctx, tc.blockGasUsed) expected := sdk.NewDecFromInt(sdk.NewInt(int64(tc.expectedBaseFee))) height := ctx.BlockHeight() - require.Equal(t, expected, k.GetDynamicBaseFeePerGas(ctx.WithBlockHeight(height+1)), "base fee did not match expected value") + gotCurrentBaseFee := k.GetCurrBaseFeePerGas(ctx.WithBlockHeight(height)) + require.InDelta(t, tc.currentBaseFee, gotCurrentBaseFee.MustFloat64(), 0.001, "base fee did not match expected value") + gotPrevBlockBaseFee := k.GetNextBaseFeePerGas(ctx.WithBlockHeight(height)) + require.Equal(t, expected, gotPrevBlockBaseFee, 0.001, "prev block base fee did not match expected value") }) } } @@ -187,15 +190,28 @@ func TestGetDynamicBaseFeePerGasWithNilMinFee(t *testing.T) { store.Delete(types.BaseFeePerGasPrefix) // Clear the dynamic base fee from store - fee := k.GetDynamicBaseFeePerGas(ctx) + fee := k.GetCurrBaseFeePerGas(ctx) require.Equal(t, types.DefaultParams().MinimumFeePerGas, fee) require.False(t, fee.IsNil()) // Test case 2: When dynamic base fee exists expectedFee := sdk.NewDec(100) - k.SetDynamicBaseFeePerGas(ctx, expectedFee) + k.SetCurrBaseFeePerGas(ctx, expectedFee) - fee = k.GetDynamicBaseFeePerGas(ctx) + fee = k.GetCurrBaseFeePerGas(ctx) require.Equal(t, expectedFee, fee) require.False(t, fee.IsNil()) } + +func TestGetPrevBlockBaseFeePerGasWithNilMinFee(t *testing.T) { + k, ctx := testkeeper.MockEVMKeeper() + + // Test case 1: When dynamic base fee doesn't exist and minimum fee is nil + store := ctx.KVStore(k.GetStoreKey()) + store.Delete(types.BaseFeePerGasPrefix) + + // Clear the dynamic base fee from store + fee := k.GetCurrBaseFeePerGas(ctx) + require.Equal(t, types.DefaultParams().MinimumFeePerGas, fee) + require.False(t, fee.IsNil()) +} diff --git a/x/evm/keeper/keeper.go b/x/evm/keeper/keeper.go index 9b754398e3..83440e7a0d 100644 --- a/x/evm/keeper/keeper.go +++ b/x/evm/keeper/keeper.go @@ -210,7 +210,7 @@ func (k *Keeper) GetVMBlockContext(ctx sdk.Context, gp core.GasPool) (*vm.BlockC BlockNumber: big.NewInt(ctx.BlockHeight()), Time: uint64(ctx.BlockHeader().Time.Unix()), Difficulty: utils.Big0, // only needed for PoW - BaseFee: k.GetDynamicBaseFeePerGas(ctx).TruncateInt().BigInt(), + BaseFee: k.GetCurrBaseFeePerGas(ctx).TruncateInt().BigInt(), BlobBaseFee: utils.Big1, // Cancun not enabled Random: &rh, }, nil diff --git a/x/evm/keeper/params_test.go b/x/evm/keeper/params_test.go index 7bbd6cb0a5..1d4fa86c35 100644 --- a/x/evm/keeper/params_test.go +++ b/x/evm/keeper/params_test.go @@ -15,7 +15,7 @@ func TestParams(t *testing.T) { ctx := testkeeper.EVMTestApp.GetContextForDeliverTx([]byte{}).WithBlockTime(time.Now()) require.Equal(t, "usei", k.GetBaseDenom(ctx)) require.Equal(t, types.DefaultPriorityNormalizer, k.GetPriorityNormalizer(ctx)) - require.Equal(t, types.DefaultMinFeePerGas, k.GetDynamicBaseFeePerGas(ctx)) + require.Equal(t, types.DefaultMinFeePerGas, k.GetCurrBaseFeePerGas(ctx)) require.Equal(t, types.DefaultBaseFeePerGas, k.GetBaseFeePerGas(ctx)) require.Equal(t, types.DefaultMinFeePerGas, k.GetMinimumFeePerGas(ctx)) require.Equal(t, types.DefaultMaxFeePerGas, k.GetMaximumFeePerGas(ctx)) diff --git a/x/evm/migrations/migrate_base_fee_off_by_one.go b/x/evm/migrations/migrate_base_fee_off_by_one.go new file mode 100644 index 0000000000..28262e6024 --- /dev/null +++ b/x/evm/migrations/migrate_base_fee_off_by_one.go @@ -0,0 +1,12 @@ +package migrations + +import ( + sdk "github.com/cosmos/cosmos-sdk/types" + "github.com/sei-protocol/sei-chain/x/evm/keeper" +) + +func MigrateBaseFeeOffByOne(ctx sdk.Context, k *keeper.Keeper) error { + baseFee := k.GetCurrBaseFeePerGas(ctx) + k.SetNextBaseFeePerGas(ctx, baseFee) + return nil +} diff --git a/x/evm/migrations/migrate_base_fee_off_by_one_test.go b/x/evm/migrations/migrate_base_fee_off_by_one_test.go new file mode 100644 index 0000000000..79be90e7d2 --- /dev/null +++ b/x/evm/migrations/migrate_base_fee_off_by_one_test.go @@ -0,0 +1,22 @@ +package migrations_test + +import ( + "testing" + + sdk "github.com/cosmos/cosmos-sdk/types" + testkeeper "github.com/sei-protocol/sei-chain/testutil/keeper" + "github.com/sei-protocol/sei-chain/x/evm/migrations" + "github.com/stretchr/testify/require" +) + +func TestMigrateBaseFeeOffByOne(t *testing.T) { + k := testkeeper.EVMTestApp.EvmKeeper + ctx := testkeeper.EVMTestApp.GetContextForDeliverTx([]byte{}).WithBlockHeight(8) + bf := sdk.NewDec(100) + k.SetCurrBaseFeePerGas(ctx, bf) + require.Equal(t, k.GetMinimumFeePerGas(ctx), k.GetNextBaseFeePerGas(ctx)) + // do the migration + require.Nil(t, migrations.MigrateBaseFeeOffByOne(ctx, &k)) + require.Equal(t, bf, k.GetNextBaseFeePerGas(ctx)) + require.Equal(t, bf, k.GetCurrBaseFeePerGas(ctx)) +} diff --git a/x/evm/module.go b/x/evm/module.go index 4265042350..54bb57cd05 100644 --- a/x/evm/module.go +++ b/x/evm/module.go @@ -229,6 +229,10 @@ func (am AppModule) RegisterServices(cfg module.Configurator) { _ = cfg.RegisterMigration(types.ModuleName, 15, func(ctx sdk.Context) error { return migrations.StoreCWPointerCode(ctx, am.keeper, false, false, true) }) + + _ = cfg.RegisterMigration(types.ModuleName, 16, func(ctx sdk.Context) error { + return migrations.MigrateBaseFeeOffByOne(ctx, am.keeper) + }) } // RegisterInvariants registers the capability module's invariants. @@ -266,7 +270,7 @@ func (am AppModule) ExportGenesisStream(ctx sdk.Context, cdc codec.JSONCodec) <- } // ConsensusVersion implements ConsensusVersion. -func (AppModule) ConsensusVersion() uint64 { return 15 } +func (AppModule) ConsensusVersion() uint64 { return 16 } // BeginBlock executes all ABCI BeginBlock logic respective to the capability module. func (am AppModule) BeginBlock(ctx sdk.Context, _ abci.RequestBeginBlock) { diff --git a/x/evm/module_test.go b/x/evm/module_test.go index 179f24ff1d..8064b4696f 100644 --- a/x/evm/module_test.go +++ b/x/evm/module_test.go @@ -60,7 +60,7 @@ func TestModuleExportGenesis(t *testing.T) { func TestConsensusVersion(t *testing.T) { k, _ := testkeeper.MockEVMKeeper() module := evm.NewAppModule(nil, k) - assert.Equal(t, uint64(15), module.ConsensusVersion()) + assert.Equal(t, uint64(16), module.ConsensusVersion()) } func TestABCI(t *testing.T) { diff --git a/x/evm/types/keys.go b/x/evm/types/keys.go index 1a72b7a852..da9064d409 100644 --- a/x/evm/types/keys.go +++ b/x/evm/types/keys.go @@ -57,6 +57,7 @@ var ( LegacyBlockBloomCutoffHeightKey = []byte{0x1a} BaseFeePerGasPrefix = []byte{0x1b} + NextBaseFeePerGasPrefix = []byte{0x1c} ) var (