Skip to content
This repository has been archived by the owner on Apr 4, 2024. It is now read-only.

change basefee to be a module param #943

Merged
merged 12 commits into from
Feb 23, 2022
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,7 @@ Ref: https://keepachangelog.com/en/1.0.0/
* (evm) [tharsis#901](https://github.com/tharsis/ethermint/pull/901) Support multiple MsgEthereumTx in single tx.
* (config) [tharsis#908](https://github.com/tharsis/ethermint/pull/908) Add api.enable flag for Cosmos SDK Rest server
* (feemarket) [tharsis#919](https://github.com/tharsis/ethermint/pull/919) Initialize baseFee in default genesis state.
* (feemarket) [tharsis#943](https://github.com/tharsis/ethermint/pull/943) Store the base fee as a module param instead of using state storage.

### Bug Fixes

Expand Down
3 changes: 2 additions & 1 deletion app/ante/utils_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,8 @@ func (suite *AnteTestSuite) SetupTest() {
feemarketGenesis := feemarkettypes.DefaultGenesisState()
feemarketGenesis.Params.EnableHeight = 1
feemarketGenesis.Params.NoBaseFee = false
feemarketGenesis.BaseFee = sdk.NewInt(feemarketGenesis.Params.InitialBaseFee)
bf, _ := sdk.NewIntFromString(feemarketGenesis.Params.BaseFee)
feemarketGenesis.DefaultBaseFee = bf
// Verify feeMarket genesis
err := feemarketGenesis.Validate()
suite.Require().NoError(err)
Expand Down
6 changes: 2 additions & 4 deletions client/docs/statik/statik.go

Large diffs are not rendered by default.

4 changes: 2 additions & 2 deletions docs/api/proto-docs.md
Original file line number Diff line number Diff line change
Expand Up @@ -923,7 +923,7 @@ Params defines the EVM module parameters
| `no_base_fee` | [bool](#bool) | | no base fee forces the EIP-1559 base fee to 0 (needed for 0 price calls) |
| `base_fee_change_denominator` | [uint32](#uint32) | | base fee change denominator bounds the amount the base fee can change between blocks. |
| `elasticity_multiplier` | [uint32](#uint32) | | elasticity multiplier bounds the maximum gas limit an EIP-1559 block may have. |
| `initial_base_fee` | [int64](#int64) | | initial base fee for EIP-1559 blocks. |
| `base_fee` | [string](#string) | | base fee for EIP-1559 blocks. |
| `enable_height` | [int64](#int64) | | height at which the base fee calculation is enabled. |


Expand Down Expand Up @@ -956,7 +956,7 @@ GenesisState defines the feemarket module's genesis state.
| Field | Type | Label | Description |
| ----- | ---- | ----- | ----------- |
| `params` | [Params](#ethermint.feemarket.v1.Params) | | params defines all the paramaters of the module. |
| `base_fee` | [string](#string) | | base fee is the exported value from previous software version. Zero by default. |
| `default_base_fee` | [string](#string) | | default base fee is the exported value from previous software version. Zero by default. |
| `block_gas` | [uint64](#uint64) | | block gas is the amount of gas used on the last block before the upgrade. Zero by default. |


Expand Down
4 changes: 2 additions & 2 deletions proto/ethermint/feemarket/v1/feemarket.proto
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,8 @@ message Params {
// elasticity multiplier bounds the maximum gas limit an EIP-1559 block may
// have.
uint32 elasticity_multiplier = 3;
// initial base fee for EIP-1559 blocks.
int64 initial_base_fee = 4;
// base fee for EIP-1559 blocks.
string base_fee = 4;
// height at which the base fee calculation is enabled.
int64 enable_height = 5;
}
4 changes: 2 additions & 2 deletions proto/ethermint/feemarket/v1/genesis.proto
Original file line number Diff line number Diff line change
Expand Up @@ -10,9 +10,9 @@ option go_package = "github.com/tharsis/ethermint/x/feemarket/types";
message GenesisState {
// params defines all the paramaters of the module.
Params params = 1 [ (gogoproto.nullable) = false ];
// base fee is the exported value from previous software version.
// default base fee is the exported value from previous software version.
// Zero by default.
string base_fee = 2 [
string default_base_fee = 2 [
(gogoproto.customtype) = "github.com/cosmos/cosmos-sdk/types.Int",
(gogoproto.nullable) = false
];
Expand Down
23 changes: 3 additions & 20 deletions rpc/ethereum/backend/backend.go
Original file line number Diff line number Diff line change
Expand Up @@ -968,33 +968,16 @@ func (e *EVMBackend) BaseFee(height int64) (*big.Int, error) {
}

// Checks the feemarket param NoBaseFee settings, return 0 if it is enabled.
resParams, err := e.queryClient.FeeMarket.Params(types.ContextWithHeight(height), &feemarkettypes.QueryParamsRequest{})
res, err := e.queryClient.FeeMarket.BaseFee(types.ContextWithHeight(height), &feemarkettypes.QueryBaseFeeRequest{})
if err != nil {
return nil, err
}

if resParams.Params.NoBaseFee {
if res.BaseFee == nil {
return big.NewInt(0), nil
}

blockRes, err := e.clientCtx.Client.BlockResults(e.ctx, &height)
if err != nil {
return nil, err
}

baseFee := types.BaseFeeFromEvents(blockRes.BeginBlockEvents)
if baseFee != nil {
return baseFee, nil
}

// If we cannot find in events, we tried to get it from the state.
// It will return feemarket.baseFee if london is activated but feemarket is not enable
res, err := e.queryClient.FeeMarket.BaseFee(types.ContextWithHeight(height), &feemarkettypes.QueryBaseFeeRequest{})
if err == nil && res.BaseFee != nil {
return res.BaseFee.BigInt(), nil
}

return nil, nil
return res.BaseFee.BigInt(), nil
}

// GetEthereumMsgsFromTendermintBlock returns all real MsgEthereumTxs from a Tendermint block.
Expand Down
14 changes: 12 additions & 2 deletions rpc/ethereum/namespaces/eth/filters/api.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ package filters
import (
"context"
"fmt"
"math/big"
"sync"
"time"

Expand Down Expand Up @@ -36,6 +37,7 @@ type Backend interface {
RPCFilterCap() int32
RPCLogsCap() int32
RPCBlockRangeCap() int32
BaseFee(height int64) (*big.Int, error)
}

// consider a filter inactive if it has not been polled for within deadline
Expand Down Expand Up @@ -258,7 +260,11 @@ func (api *PublicFilterAPI) NewBlockFilter() rpc.ID {
continue
}

baseFee := types.BaseFeeFromEvents(data.ResultBeginBlock.Events)
baseFee, err := api.backend.BaseFee(data.Header.Height)
if err != nil {
api.logger.Debug("cannot retrieve base fee", "err", fmt.Sprintf("%v", err))
continue
}

header := types.EthHeaderFromTendermint(data.Header, ethtypes.Bloom{}, baseFee)
api.filtersMu.Lock()
Expand Down Expand Up @@ -310,7 +316,11 @@ func (api *PublicFilterAPI) NewHeads(ctx context.Context) (*rpc.Subscription, er
continue
}

baseFee := types.BaseFeeFromEvents(data.ResultBeginBlock.Events)
baseFee, err := api.backend.BaseFee(data.Header.Height)
if err != nil {
api.logger.Debug("cannot retrieve base fee", "err", fmt.Sprintf("%v", err))
continue
}

// TODO: fetch bloom from events
header := types.EthHeaderFromTendermint(data.Header, ethtypes.Bloom{}, baseFee)
Expand Down
25 changes: 1 addition & 24 deletions rpc/ethereum/types/utils.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,13 +14,11 @@ import (
"github.com/cosmos/cosmos-sdk/client"
sdkerrors "github.com/cosmos/cosmos-sdk/types/errors"

evmtypes "github.com/tharsis/ethermint/x/evm/types"
feemarkettypes "github.com/tharsis/ethermint/x/feemarket/types"

"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/common/hexutil"
"github.com/ethereum/go-ethereum/common/math"
ethtypes "github.com/ethereum/go-ethereum/core/types"
evmtypes "github.com/tharsis/ethermint/x/evm/types"
)

// RawTxToEthTx returns a evm MsgEthereum transaction from raw tx bytes.
Expand Down Expand Up @@ -234,27 +232,6 @@ func NewRPCTransaction(
return result, nil
}

// BaseFeeFromEvents parses the feemarket basefee from cosmos events
func BaseFeeFromEvents(events []abci.Event) *big.Int {
for _, event := range events {
if event.Type != feemarkettypes.EventTypeFeeMarket {
continue
}

for _, attr := range event.Attributes {
if bytes.Equal(attr.Key, []byte(feemarkettypes.AttributeKeyBaseFee)) {
result, success := new(big.Int).SetString(string(attr.Value), 10)
if success {
return result
}

return nil
}
}
}
return nil
}

// FindTxAttributes returns the msg index of the eth tx in cosmos tx, and the attributes,
// returns -1 and nil if not found.
func FindTxAttributes(events []abci.Event, txHash string) (int, map[string]string) {
Expand Down
5 changes: 3 additions & 2 deletions x/evm/keeper/keeper_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -91,10 +91,11 @@ func (suite *KeeperTestSuite) DoSetupTest(t require.TestingT) {
if suite.enableFeemarket {
feemarketGenesis.Params.EnableHeight = 1
feemarketGenesis.Params.NoBaseFee = false
feemarketGenesis.BaseFee = sdk.NewInt(feemarketGenesis.Params.InitialBaseFee)
bf, _ := sdk.NewIntFromString(feemarketGenesis.Params.BaseFee)
feemarketGenesis.DefaultBaseFee = bf
} else {
feemarketGenesis.Params.NoBaseFee = true
feemarketGenesis.BaseFee = sdk.NewInt(0)
feemarketGenesis.DefaultBaseFee = sdk.NewInt(0)
}
genesis[feemarkettypes.ModuleName] = app.AppCodec().MustMarshalJSON(feemarketGenesis)
if !suite.enableLondonHF {
Expand Down
7 changes: 3 additions & 4 deletions x/feemarket/genesis.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,6 @@ func InitGenesis(
data types.GenesisState,
) []abci.ValidatorUpdate {
k.SetParams(ctx, data.Params)
k.SetBaseFee(ctx, data.BaseFee.BigInt())
k.SetBlockGasUsed(ctx, data.BlockGas)

return []abci.ValidatorUpdate{}
Expand All @@ -30,8 +29,8 @@ func ExportGenesis(ctx sdk.Context, k keeper.Keeper) *types.GenesisState {
}

return &types.GenesisState{
Params: k.GetParams(ctx),
BaseFee: baseFee,
BlockGas: k.GetBlockGasUsed(ctx),
Params: k.GetParams(ctx),
DefaultBaseFee: baseFee,
BlockGas: k.GetBlockGasUsed(ctx),
}
}
12 changes: 1 addition & 11 deletions x/feemarket/keeper/abci.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,8 @@ package keeper
import (
"fmt"

abci "github.com/tendermint/tendermint/abci/types"
"github.com/tharsis/ethermint/x/feemarket/types"

sdk "github.com/cosmos/cosmos-sdk/types"
abci "github.com/tendermint/tendermint/abci/types"
)

// BeginBlock updates base fee
Expand All @@ -19,14 +17,6 @@ func (k *Keeper) BeginBlock(ctx sdk.Context, req abci.RequestBeginBlock) {
}

k.SetBaseFee(ctx, baseFee)

// Store current base fee in event
ctx.EventManager().EmitEvents(sdk.Events{
sdk.NewEvent(
types.EventTypeFeeMarket,
sdk.NewAttribute(types.AttributeKeyBaseFee, baseFee.String()),
),
})
}

// EndBlock update block gas used.
Expand Down
6 changes: 3 additions & 3 deletions x/feemarket/keeper/eip1559.go
Original file line number Diff line number Diff line change
Expand Up @@ -25,13 +25,13 @@ func (k Keeper) CalculateBaseFee(ctx sdk.Context) *big.Int {

// If the current block is the first EIP-1559 block, return the InitialBaseFee.
if ctx.BlockHeight() == params.EnableHeight {
return new(big.Int).SetInt64(params.InitialBaseFee)
return k.GetBaseFee(ctx)
}

// get the block gas used and the base fee values for the parent block.
parentBaseFee := k.GetBaseFee(ctx)
if parentBaseFee == nil {
parentBaseFee = new(big.Int).SetInt64(params.InitialBaseFee)
return nil
}

parentGasUsed := k.GetBlockGasUsed(ctx)
Expand All @@ -43,7 +43,7 @@ func (k Keeper) CalculateBaseFee(ctx sdk.Context) *big.Int {

parentGasTargetBig := new(big.Int).Div(gasLimit, new(big.Int).SetUint64(uint64(params.ElasticityMultiplier)))
if !parentGasTargetBig.IsUint64() {
return new(big.Int).SetInt64(params.InitialBaseFee)
return nil
}

parentGasTarget := parentGasTargetBig.Uint64()
Expand Down
16 changes: 7 additions & 9 deletions x/feemarket/keeper/eip1559_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,6 @@ package keeper_test

import (
"fmt"
"math/big"

abci "github.com/tendermint/tendermint/abci/types"
)

Expand All @@ -12,21 +10,21 @@ func (suite *KeeperTestSuite) TestCalculateBaseFee() {
name string
NoBaseFee bool
malleate func()
expFee *big.Int
expFee string
}{
{
"without BaseFee",
true,
func() {},
nil,
"",
},
{
"with BaseFee - initial EIP-1559 block",
false,
func() {
suite.ctx = suite.ctx.WithBlockHeight(0)
},
big.NewInt(suite.app.FeeMarketKeeper.GetParams(suite.ctx).InitialBaseFee),
suite.app.FeeMarketKeeper.GetParams(suite.ctx).BaseFee,
},
{
"with BaseFee - parent block used the same gas as its target",
Expand All @@ -51,7 +49,7 @@ func (suite *KeeperTestSuite) TestCalculateBaseFee() {
params.ElasticityMultiplier = 1
suite.app.FeeMarketKeeper.SetParams(suite.ctx, params)
},
big.NewInt(suite.app.FeeMarketKeeper.GetParams(suite.ctx).InitialBaseFee),
suite.app.FeeMarketKeeper.GetParams(suite.ctx).BaseFee,
},
{
"with BaseFee - parent block used more gas than its target",
Expand All @@ -72,7 +70,7 @@ func (suite *KeeperTestSuite) TestCalculateBaseFee() {
params.ElasticityMultiplier = 1
suite.app.FeeMarketKeeper.SetParams(suite.ctx, params)
},
big.NewInt(1125000000),
"1125000000",
},
{
"with BaseFee - Parent gas used smaller than parent gas target",
Expand All @@ -93,7 +91,7 @@ func (suite *KeeperTestSuite) TestCalculateBaseFee() {
params.ElasticityMultiplier = 1
suite.app.FeeMarketKeeper.SetParams(suite.ctx, params)
},
big.NewInt(937500000),
"937500000",
},
}
for _, tc := range testCases {
Expand All @@ -109,7 +107,7 @@ func (suite *KeeperTestSuite) TestCalculateBaseFee() {
if tc.NoBaseFee {
suite.Require().Nil(fee, tc.name)
} else {
suite.Require().Equal(tc.expFee, fee, tc.name)
suite.Require().Equal(tc.expFee, fee.String(), tc.name)
}
})
}
Expand Down
8 changes: 8 additions & 0 deletions x/feemarket/keeper/grpc_query.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,10 +21,18 @@ func (k Keeper) Params(c context.Context, _ *types.QueryParamsRequest) (*types.Q
}

// BaseFee implements the Query/BaseFee gRPC method
// return empty if base fee is not enable
func (k Keeper) BaseFee(c context.Context, _ *types.QueryBaseFeeRequest) (*types.QueryBaseFeeResponse, error) {
ctx := sdk.UnwrapSDKContext(c)

res := &types.QueryBaseFeeResponse{}

params := k.GetParams(ctx)

if params.NoBaseFee {
return res, nil
}

baseFee := k.GetBaseFee(ctx)

if baseFee != nil {
Expand Down
26 changes: 0 additions & 26 deletions x/feemarket/keeper/keeper.go
Original file line number Diff line number Diff line change
@@ -1,8 +1,6 @@
package keeper

import (
"math/big"

"github.com/cosmos/cosmos-sdk/codec"
sdk "github.com/cosmos/cosmos-sdk/types"
paramtypes "github.com/cosmos/cosmos-sdk/x/params/types"
Expand Down Expand Up @@ -65,27 +63,3 @@ func (k Keeper) SetBlockGasUsed(ctx sdk.Context, gas uint64) {
gasBz := sdk.Uint64ToBigEndian(gas)
store.Set(types.KeyPrefixBlockGasUsed, gasBz)
}

// ----------------------------------------------------------------------------
// Parent Base Fee
// Required by EIP1559 base fee calculation.
// ----------------------------------------------------------------------------

// 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 {
store := ctx.KVStore(k.storeKey)
bz := store.Get(types.KeyPrefixBaseFee)
if len(bz) == 0 {
return nil
}

return new(big.Int).SetBytes(bz)
}

// SetBaseFee set the last base fee value to the store.
// CONTRACT: this should be only called during EndBlock.
func (k Keeper) SetBaseFee(ctx sdk.Context, baseFee *big.Int) {
store := ctx.KVStore(k.storeKey)
store.Set(types.KeyPrefixBaseFee, baseFee.Bytes())
}
Loading