update fork

This commit is contained in:
0xmuralik
2022-10-10 16:08:33 +05:30
parent 632d53e34a
commit 56d59feaa0
383 changed files with 36784 additions and 21462 deletions
+6 -35
View File
@@ -1,16 +1,10 @@
package cli
import (
"context"
"fmt"
"strconv"
"github.com/spf13/cobra"
"google.golang.org/grpc/metadata"
"github.com/cosmos/cosmos-sdk/client"
"github.com/cosmos/cosmos-sdk/client/flags"
grpctypes "github.com/cosmos/cosmos-sdk/types/grpc"
"github.com/cerc-io/laconicd/x/feemarket/types"
)
@@ -36,27 +30,20 @@ func GetQueryCmd() *cobra.Command {
// GetBlockGasCmd queries the gas used in a block
func GetBlockGasCmd() *cobra.Command {
cmd := &cobra.Command{
Use: "block-gas [height]",
Use: "block-gas",
Short: "Get the block gas used at a given block height",
Long: `Get the block gas used at a given block height.
If the height is not provided, it will use the latest height from context`,
Args: cobra.RangeArgs(0, 1),
Args: cobra.NoArgs,
RunE: func(cmd *cobra.Command, args []string) error {
clientCtx, err := client.GetClientQueryContext(cmd)
if err != nil {
return err
}
ctx := cmd.Context()
if len(args) == 1 {
ctx, err = getContextHeight(ctx, args[0])
if err != nil {
return err
}
}
queryClient := types.NewQueryClient(clientCtx)
ctx := cmd.Context()
res, err := queryClient.BlockGas(ctx, &types.QueryBlockGasRequest{})
if err != nil {
return err
@@ -101,27 +88,20 @@ func GetParamsCmd() *cobra.Command {
// GetBaseFeeCmd queries the base fee at a given height
func GetBaseFeeCmd() *cobra.Command {
cmd := &cobra.Command{
Use: "base-fee [height]",
Use: "base-fee",
Short: "Get the base fee amount at a given block height",
Long: `Get the base fee amount at a given block height.
If the height is not provided, it will use the latest height from context.`,
Args: cobra.RangeArgs(0, 1),
Args: cobra.NoArgs,
RunE: func(cmd *cobra.Command, args []string) error {
clientCtx, err := client.GetClientQueryContext(cmd)
if err != nil {
return err
}
ctx := cmd.Context()
if len(args) == 1 {
ctx, err = getContextHeight(ctx, args[0])
if err != nil {
return err
}
}
queryClient := types.NewQueryClient(clientCtx)
ctx := cmd.Context()
res, err := queryClient.BaseFee(ctx, &types.QueryBaseFeeRequest{})
if err != nil {
return err
@@ -134,12 +114,3 @@ If the height is not provided, it will use the latest height from context.`,
flags.AddQueryFlagsToCmd(cmd)
return cmd
}
func getContextHeight(ctx context.Context, height string) (context.Context, error) {
_, err := strconv.ParseInt(height, 10, 64)
if err != nil {
return ctx, fmt.Errorf("invalid height: %w", err)
}
return metadata.AppendToOutgoingContext(ctx, grpctypes.GRPCBlockHeightHeader, height), nil
}
+2 -2
View File
@@ -15,7 +15,7 @@ func InitGenesis(
data types.GenesisState,
) []abci.ValidatorUpdate {
k.SetParams(ctx, data.Params)
k.SetBlockGasUsed(ctx, data.BlockGas)
k.SetBlockGasWanted(ctx, data.BlockGas)
return []abci.ValidatorUpdate{}
}
@@ -24,6 +24,6 @@ func InitGenesis(
func ExportGenesis(ctx sdk.Context, k keeper.Keeper) *types.GenesisState {
return &types.GenesisState{
Params: k.GetParams(ctx),
BlockGas: k.GetBlockGasUsed(ctx),
BlockGas: k.GetBlockGasWanted(ctx),
}
}
+21 -4
View File
@@ -6,6 +6,7 @@ import (
"github.com/cerc-io/laconicd/x/feemarket/types"
abci "github.com/tendermint/tendermint/abci/types"
"github.com/cosmos/cosmos-sdk/telemetry"
sdk "github.com/cosmos/cosmos-sdk/types"
)
@@ -20,6 +21,10 @@ func (k *Keeper) BeginBlock(ctx sdk.Context, req abci.RequestBeginBlock) {
k.SetBaseFee(ctx, baseFee)
defer func() {
telemetry.SetGauge(float32(baseFee.Int64()), "feemarket", "base_fee")
}()
// Store current base fee in event
ctx.EventManager().EmitEvents(sdk.Events{
sdk.NewEvent(
@@ -29,22 +34,34 @@ func (k *Keeper) BeginBlock(ctx sdk.Context, req abci.RequestBeginBlock) {
})
}
// EndBlock update block gas used.
// EndBlock update block gas wanted.
// The EVM end block logic doesn't update the validator set, thus it returns
// an empty slice.
func (k *Keeper) EndBlock(ctx sdk.Context, req abci.RequestEndBlock) {
if ctx.BlockGasMeter() == nil {
k.Logger(ctx).Error("block gas meter is nil when setting block gas used")
k.Logger(ctx).Error("block gas meter is nil when setting block gas wanted")
return
}
gasWanted := k.GetTransientGasWanted(ctx)
gasUsed := ctx.BlockGasMeter().GasConsumedToLimit()
k.SetBlockGasUsed(ctx, gasUsed)
// to prevent BaseFee manipulation we limit the gasWanted so that
// gasWanted = max(gasWanted * MinGasMultiplier, gasUsed)
// this will be keep BaseFee protected from un-penalized manipulation
// more info here https://github.com/cerc-io/laconicd/pull/1105#discussion_r888798925
minGasMultiplier := k.GetParams(ctx).MinGasMultiplier
limitedGasWanted := sdk.NewDec(int64(gasWanted)).Mul(minGasMultiplier)
gasWanted = sdk.MaxDec(limitedGasWanted, sdk.NewDec(int64(gasUsed))).TruncateInt().Uint64()
k.SetBlockGasWanted(ctx, gasWanted)
defer func() {
telemetry.SetGauge(float32(gasWanted), "feemarket", "block_gas")
}()
ctx.EventManager().EmitEvent(sdk.NewEvent(
"block_gas",
sdk.NewAttribute("height", fmt.Sprintf("%d", ctx.BlockHeight())),
sdk.NewAttribute("amount", fmt.Sprintf("%d", ctx.BlockGasMeter().GasConsumedToLimit())),
sdk.NewAttribute("amount", fmt.Sprintf("%d", gasWanted)),
))
}
+11 -19
View File
@@ -4,37 +4,31 @@ import (
"fmt"
sdk "github.com/cosmos/cosmos-sdk/types"
abci "github.com/tendermint/tendermint/abci/types"
"github.com/tendermint/tendermint/abci/types"
)
func (suite *KeeperTestSuite) TestEndBlock() {
testCases := []struct {
name string
NoBaseFee bool
malleate func()
expGasUsed uint64
name string
NoBaseFee bool
malleate func()
expGasWanted uint64
}{
{
"basFee nil",
"baseFee nil",
true,
func() {},
uint64(0),
},
{
"Block gas meter is nil",
false,
func() {},
uint64(0),
},
{
"pass",
false,
func() {
meter := sdk.NewGasMeter(uint64(1000000000))
suite.ctx = suite.ctx.WithBlockGasMeter(meter)
suite.ctx.BlockGasMeter().ConsumeGas(uint64(5000000), "consume gas")
suite.app.FeeMarketKeeper.SetTransientBlockGasWanted(suite.ctx, 5000000)
},
uint64(5000000),
uint64(2500000),
},
}
for _, tc := range testCases {
@@ -45,11 +39,9 @@ func (suite *KeeperTestSuite) TestEndBlock() {
suite.app.FeeMarketKeeper.SetParams(suite.ctx, params)
tc.malleate()
req := abci.RequestEndBlock{Height: 1}
suite.app.FeeMarketKeeper.EndBlock(suite.ctx, req)
gasUsed := suite.app.FeeMarketKeeper.GetBlockGasUsed(suite.ctx)
suite.Require().Equal(tc.expGasUsed, gasUsed, tc.name)
suite.app.FeeMarketKeeper.EndBlock(suite.ctx, types.RequestEndBlock{Height: 1})
gasWanted := suite.app.FeeMarketKeeper.GetBlockGasWanted(suite.ctx)
suite.Require().Equal(tc.expGasWanted, gasWanted, tc.name)
})
}
}
+22 -10
View File
@@ -16,31 +16,40 @@ import (
func (k Keeper) CalculateBaseFee(ctx sdk.Context) *big.Int {
params := k.GetParams(ctx)
// Ignore the calculation if not enable
// Ignore the calculation if not enabled
if !params.IsBaseFeeEnabled(ctx.BlockHeight()) {
return nil
}
consParams := ctx.ConsensusParams()
// If the current block is the first EIP-1559 block, return the InitialBaseFee.
// If the current block is the first EIP-1559 block, return the base fee
// defined in the parameters (DefaultBaseFee if it hasn't been changed by
// governance).
if ctx.BlockHeight() == params.EnableHeight {
return params.BaseFee.BigInt()
}
// get the block gas used and the base fee values for the parent block.
// NOTE: this is not the parent's base fee but the current block's base fee,
// as it is retrieved from the transient store, which is committed to the
// persistent KVStore after EndBlock (ABCI Commit).
parentBaseFee := params.BaseFee.BigInt()
if parentBaseFee == nil {
return nil
}
parentGasUsed := k.GetBlockGasUsed(ctx)
parentGasUsed := k.GetBlockGasWanted(ctx)
gasLimit := new(big.Int).SetUint64(math.MaxUint64)
// NOTE: a MaxGas equal to -1 means that block gas is unlimited
if consParams != nil && consParams.Block.MaxGas > -1 {
gasLimit = big.NewInt(consParams.Block.MaxGas)
}
// CONTRACT: ElasticityMultiplier cannot be 0 as it's checked in the params
// validation
parentGasTargetBig := new(big.Int).Div(gasLimit, new(big.Int).SetUint64(uint64(params.ElasticityMultiplier)))
if !parentGasTargetBig.IsUint64() {
return nil
@@ -49,13 +58,15 @@ func (k Keeper) CalculateBaseFee(ctx sdk.Context) *big.Int {
parentGasTarget := parentGasTargetBig.Uint64()
baseFeeChangeDenominator := new(big.Int).SetUint64(uint64(params.BaseFeeChangeDenominator))
// If the parent gasUsed is the same as the target, the baseFee remains unchanged.
// If the parent gasUsed is the same as the target, the baseFee remains
// unchanged.
if parentGasUsed == parentGasTarget {
return new(big.Int).Set(parentBaseFee)
}
if parentGasUsed > parentGasTarget {
// If the parent block used more gas than its target, the baseFee should increase.
// If the parent block used more gas than its target, the baseFee should
// increase.
gasUsedDelta := new(big.Int).SetUint64(parentGasUsed - parentGasTarget)
x := new(big.Int).Mul(parentBaseFee, gasUsedDelta)
y := x.Div(x, parentGasTargetBig)
@@ -67,14 +78,15 @@ func (k Keeper) CalculateBaseFee(ctx sdk.Context) *big.Int {
return x.Add(parentBaseFee, baseFeeDelta)
}
// Otherwise if the parent block used less gas than its target, the baseFee should decrease.
// Otherwise if the parent block used less gas than its target, the baseFee
// should decrease.
gasUsedDelta := new(big.Int).SetUint64(parentGasTarget - parentGasUsed)
x := new(big.Int).Mul(parentBaseFee, gasUsedDelta)
y := x.Div(x, parentGasTargetBig)
baseFeeDelta := x.Div(y, baseFeeChangeDenominator)
return math.BigMax(
x.Sub(parentBaseFee, baseFeeDelta),
common.Big0,
)
// Set global min gas price as lower bound of the base fee, transactions below
// the min gas price don't even reach the mempool.
minGasPrice := params.MinGasPrice.TruncateInt().BigInt()
return math.BigMax(x.Sub(parentBaseFee, baseFeeDelta), minGasPrice)
}
+64 -64
View File
@@ -4,106 +4,106 @@ import (
"fmt"
"math/big"
sdk "github.com/cosmos/cosmos-sdk/types"
abci "github.com/tendermint/tendermint/abci/types"
)
func (suite *KeeperTestSuite) TestCalculateBaseFee() {
testCases := []struct {
name string
NoBaseFee bool
malleate func()
expFee *big.Int
name string
NoBaseFee bool
blockHeight int64
parentBlockGasWanted uint64
minGasPrice sdk.Dec
expFee *big.Int
}{
{
"without BaseFee",
true,
func() {},
0,
0,
sdk.ZeroDec(),
nil,
},
{
"with BaseFee - initial EIP-1559 block",
false,
func() {
suite.ctx = suite.ctx.WithBlockHeight(0)
},
0,
0,
sdk.ZeroDec(),
suite.app.FeeMarketKeeper.GetParams(suite.ctx).BaseFee.BigInt(),
},
{
"with BaseFee - parent block used the same gas as its target",
"with BaseFee - parent block wanted the same gas as its target (ElasticityMultiplier = 2)",
false,
func() {
// non initial block
suite.ctx = suite.ctx.WithBlockHeight(1)
// Set gas used
suite.app.FeeMarketKeeper.SetBlockGasUsed(suite.ctx, 100)
// Set target/gasLimit through Consensus Param MaxGas
blockParams := abci.BlockParams{
MaxGas: 100,
MaxBytes: 10,
}
consParams := abci.ConsensusParams{Block: &blockParams}
suite.ctx = suite.ctx.WithConsensusParams(&consParams)
// set ElasticityMultiplier
params := suite.app.FeeMarketKeeper.GetParams(suite.ctx)
params.ElasticityMultiplier = 1
suite.app.FeeMarketKeeper.SetParams(suite.ctx, params)
},
1,
50,
sdk.ZeroDec(),
suite.app.FeeMarketKeeper.GetParams(suite.ctx).BaseFee.BigInt(),
},
{
"with BaseFee - parent block used more gas than its target",
"with BaseFee - parent block wanted the same gas as its target, with higher min gas price (ElasticityMultiplier = 2)",
false,
func() {
suite.ctx = suite.ctx.WithBlockHeight(1)
suite.app.FeeMarketKeeper.SetBlockGasUsed(suite.ctx, 200)
blockParams := abci.BlockParams{
MaxGas: 100,
MaxBytes: 10,
}
consParams := abci.ConsensusParams{Block: &blockParams}
suite.ctx = suite.ctx.WithConsensusParams(&consParams)
params := suite.app.FeeMarketKeeper.GetParams(suite.ctx)
params.ElasticityMultiplier = 1
suite.app.FeeMarketKeeper.SetParams(suite.ctx, params)
},
1,
50,
sdk.NewDec(1500000000),
suite.app.FeeMarketKeeper.GetParams(suite.ctx).BaseFee.BigInt(),
},
{
"with BaseFee - parent block wanted more gas than its target (ElasticityMultiplier = 2)",
false,
1,
100,
sdk.ZeroDec(),
big.NewInt(1125000000),
},
{
"with BaseFee - Parent gas used smaller than parent gas target",
"with BaseFee - parent block wanted more gas than its target, with higher min gas price (ElasticityMultiplier = 2)",
false,
func() {
suite.ctx = suite.ctx.WithBlockHeight(1)
suite.app.FeeMarketKeeper.SetBlockGasUsed(suite.ctx, 50)
blockParams := abci.BlockParams{
MaxGas: 100,
MaxBytes: 10,
}
consParams := abci.ConsensusParams{Block: &blockParams}
suite.ctx = suite.ctx.WithConsensusParams(&consParams)
params := suite.app.FeeMarketKeeper.GetParams(suite.ctx)
params.ElasticityMultiplier = 1
suite.app.FeeMarketKeeper.SetParams(suite.ctx, params)
},
1,
100,
sdk.NewDec(1500000000),
big.NewInt(1125000000),
},
{
"with BaseFee - Parent gas wanted smaller than parent gas target (ElasticityMultiplier = 2)",
false,
1,
25,
sdk.ZeroDec(),
big.NewInt(937500000),
},
{
"with BaseFee - Parent gas wanted smaller than parent gas target, with higher min gas price (ElasticityMultiplier = 2)",
false,
1,
25,
sdk.NewDec(1500000000),
big.NewInt(1500000000),
},
}
for _, tc := range testCases {
suite.Run(fmt.Sprintf("Case %s", tc.name), func() {
suite.SetupTest() // reset
params := suite.app.FeeMarketKeeper.GetParams(suite.ctx)
params.NoBaseFee = tc.NoBaseFee
params.MinGasPrice = tc.minGasPrice
suite.app.FeeMarketKeeper.SetParams(suite.ctx, params)
tc.malleate()
// Set block height
suite.ctx = suite.ctx.WithBlockHeight(tc.blockHeight)
// Set parent block gas
suite.app.FeeMarketKeeper.SetBlockGasWanted(suite.ctx, tc.parentBlockGasWanted)
// Set next block target/gasLimit through Consensus Param MaxGas
blockParams := abci.BlockParams{
MaxGas: 100,
MaxBytes: 10,
}
consParams := abci.ConsensusParams{Block: &blockParams}
suite.ctx = suite.ctx.WithConsensusParams(&consParams)
fee := suite.app.FeeMarketKeeper.CalculateBaseFee(suite.ctx)
if tc.NoBaseFee {
+3 -2
View File
@@ -3,6 +3,7 @@ package keeper
import (
"context"
sdkmath "cosmossdk.io/math"
sdk "github.com/cosmos/cosmos-sdk/types"
"github.com/cerc-io/laconicd/x/feemarket/types"
@@ -28,7 +29,7 @@ func (k Keeper) BaseFee(c context.Context, _ *types.QueryBaseFeeRequest) (*types
baseFee := k.GetBaseFee(ctx)
if baseFee != nil {
aux := sdk.NewIntFromBigInt(baseFee)
aux := sdkmath.NewIntFromBigInt(baseFee)
res.BaseFee = &aux
}
@@ -38,7 +39,7 @@ func (k Keeper) BaseFee(c context.Context, _ *types.QueryBaseFeeRequest) (*types
// BlockGas implements the Query/BlockGas gRPC method
func (k Keeper) BlockGas(c context.Context, _ *types.QueryBlockGasRequest) (*types.QueryBlockGasResponse, error) {
ctx := sdk.UnwrapSDKContext(c)
gas := k.GetBlockGasUsed(ctx)
gas := k.GetBlockGasWanted(ctx)
return &types.QueryBlockGasResponse{
Gas: int64(gas),
+5 -4
View File
@@ -1,6 +1,7 @@
package keeper_test
import (
sdkmath "cosmossdk.io/math"
"github.com/cerc-io/laconicd/x/feemarket/types"
sdk "github.com/cosmos/cosmos-sdk/types"
ethparams "github.com/ethereum/go-ethereum/params"
@@ -32,7 +33,7 @@ func (suite *KeeperTestSuite) TestQueryParams() {
func (suite *KeeperTestSuite) TestQueryBaseFee() {
var (
aux sdk.Int
aux sdkmath.Int
expRes *types.QueryBaseFeeResponse
)
@@ -44,7 +45,7 @@ func (suite *KeeperTestSuite) TestQueryBaseFee() {
{
"pass - default Base Fee",
func() {
initialBaseFee := sdk.NewInt(ethparams.InitialBaseFee)
initialBaseFee := sdkmath.NewInt(ethparams.InitialBaseFee)
expRes = &types.QueryBaseFeeResponse{BaseFee: &initialBaseFee}
},
true,
@@ -55,7 +56,7 @@ func (suite *KeeperTestSuite) TestQueryBaseFee() {
baseFee := sdk.OneInt().BigInt()
suite.app.FeeMarketKeeper.SetBaseFee(suite.ctx, baseFee)
aux = sdk.NewIntFromBigInt(baseFee)
aux = sdkmath.NewIntFromBigInt(baseFee)
expRes = &types.QueryBaseFeeResponse{BaseFee: &aux}
},
true,
@@ -86,7 +87,7 @@ func (suite *KeeperTestSuite) TestQueryBlockGas() {
},
}
for _, tc := range testCases {
gas := suite.app.FeeMarketKeeper.GetBlockGasUsed(suite.ctx)
gas := suite.app.FeeMarketKeeper.GetBlockGasWanted(suite.ctx)
exp := &types.QueryBlockGasResponse{Gas: int64(gas)}
res, err := suite.queryClient.BlockGas(suite.ctx.Context(), &types.QueryBlockGasRequest{})
+677
View File
@@ -0,0 +1,677 @@
package keeper_test
import (
"encoding/json"
"math/big"
"strings"
sdkmath "cosmossdk.io/math"
. "github.com/onsi/ginkgo/v2"
. "github.com/onsi/gomega"
"github.com/cerc-io/laconicd/app"
"github.com/cerc-io/laconicd/crypto/ethsecp256k1"
"github.com/cerc-io/laconicd/encoding"
"github.com/cerc-io/laconicd/tests"
"github.com/cerc-io/laconicd/testutil"
"github.com/cerc-io/laconicd/x/feemarket/types"
"github.com/cosmos/cosmos-sdk/baseapp"
"github.com/cosmos/cosmos-sdk/client/tx"
codectypes "github.com/cosmos/cosmos-sdk/codec/types"
sdk "github.com/cosmos/cosmos-sdk/types"
"github.com/cosmos/cosmos-sdk/types/tx/signing"
authsigning "github.com/cosmos/cosmos-sdk/x/auth/signing"
authtx "github.com/cosmos/cosmos-sdk/x/auth/tx"
"github.com/ethereum/go-ethereum/common"
ethtypes "github.com/ethereum/go-ethereum/core/types"
evmtypes "github.com/cerc-io/laconicd/x/evm/types"
"github.com/cosmos/cosmos-sdk/simapp"
banktypes "github.com/cosmos/cosmos-sdk/x/bank/types"
abci "github.com/tendermint/tendermint/abci/types"
"github.com/tendermint/tendermint/libs/log"
dbm "github.com/tendermint/tm-db"
)
var _ = Describe("Feemarket", func() {
var (
privKey *ethsecp256k1.PrivKey
msg banktypes.MsgSend
)
Describe("Performing Cosmos transactions", func() {
Context("with min-gas-prices (local) < MinGasPrices (feemarket param)", func() {
BeforeEach(func() {
privKey, msg = setupTestWithContext("1", sdk.NewDec(3), sdk.ZeroInt())
})
Context("during CheckTx", func() {
It("should reject transactions with gasPrice < MinGasPrices", func() {
gasPrice := sdkmath.NewInt(2)
res := checkTx(privKey, &gasPrice, &msg)
Expect(res.IsOK()).To(Equal(false), "transaction should have failed")
Expect(
strings.Contains(res.GetLog(),
"provided fee < minimum global fee"),
).To(BeTrue(), res.GetLog())
})
It("should accept transactions with gasPrice >= MinGasPrices", func() {
gasPrice := sdkmath.NewInt(3)
res := checkTx(privKey, &gasPrice, &msg)
Expect(res.IsOK()).To(Equal(true), "transaction should have succeeded", res.GetLog())
})
})
Context("during DeliverTx", func() {
It("should reject transactions with gasPrice < MinGasPrices", func() {
gasPrice := sdkmath.NewInt(2)
res := deliverTx(privKey, &gasPrice, &msg)
Expect(res.IsOK()).To(Equal(false), "transaction should have failed")
Expect(
strings.Contains(res.GetLog(),
"provided fee < minimum global fee"),
).To(BeTrue(), res.GetLog())
})
It("should accept transactions with gasPrice >= MinGasPrices", func() {
gasPrice := sdkmath.NewInt(3)
res := deliverTx(privKey, &gasPrice, &msg)
Expect(res.IsOK()).To(Equal(true), "transaction should have succeeded", res.GetLog())
})
})
})
Context("with min-gas-prices (local) == MinGasPrices (feemarket param)", func() {
BeforeEach(func() {
privKey, msg = setupTestWithContext("3", sdk.NewDec(3), sdk.ZeroInt())
})
Context("during CheckTx", func() {
It("should reject transactions with gasPrice < min-gas-prices", func() {
gasPrice := sdkmath.NewInt(2)
res := checkTx(privKey, &gasPrice, &msg)
Expect(res.IsOK()).To(Equal(false), "transaction should have failed")
Expect(
strings.Contains(res.GetLog(),
"insufficient fee"),
).To(BeTrue(), res.GetLog())
})
It("should accept transactions with gasPrice >= MinGasPrices", func() {
gasPrice := sdkmath.NewInt(3)
res := checkTx(privKey, &gasPrice, &msg)
Expect(res.IsOK()).To(Equal(true), "transaction should have succeeded", res.GetLog())
})
})
Context("during DeliverTx", func() {
It("should reject transactions with gasPrice < MinGasPrices", func() {
gasPrice := sdkmath.NewInt(2)
res := deliverTx(privKey, &gasPrice, &msg)
Expect(res.IsOK()).To(Equal(false), "transaction should have failed")
Expect(
strings.Contains(res.GetLog(),
"provided fee < minimum global fee"),
).To(BeTrue(), res.GetLog())
})
It("should accept transactions with gasPrice >= MinGasPrices", func() {
gasPrice := sdkmath.NewInt(3)
res := deliverTx(privKey, &gasPrice, &msg)
Expect(res.IsOK()).To(Equal(true), "transaction should have succeeded", res.GetLog())
})
})
})
Context("with MinGasPrices (feemarket param) < min-gas-prices (local)", func() {
BeforeEach(func() {
privKey, msg = setupTestWithContext("5", sdk.NewDec(3), sdk.NewInt(5))
})
Context("during CheckTx", func() {
It("should reject transactions with gasPrice < MinGasPrices", func() {
gasPrice := sdkmath.NewInt(2)
res := checkTx(privKey, &gasPrice, &msg)
Expect(res.IsOK()).To(Equal(false), "transaction should have failed")
Expect(
strings.Contains(res.GetLog(),
"insufficient fee"),
).To(BeTrue(), res.GetLog())
})
It("should reject transactions with MinGasPrices < gasPrice < baseFee", func() {
gasPrice := sdkmath.NewInt(4)
res := checkTx(privKey, &gasPrice, &msg)
Expect(res.IsOK()).To(Equal(false), "transaction should have failed")
Expect(
strings.Contains(res.GetLog(),
"insufficient fee"),
).To(BeTrue(), res.GetLog())
})
It("should accept transactions with gasPrice >= baseFee", func() {
gasPrice := sdkmath.NewInt(5)
res := checkTx(privKey, &gasPrice, &msg)
Expect(res.IsOK()).To(Equal(true), "transaction should have succeeded", res.GetLog())
})
})
Context("during DeliverTx", func() {
It("should reject transactions with gasPrice < MinGasPrices", func() {
gasPrice := sdkmath.NewInt(2)
res := deliverTx(privKey, &gasPrice, &msg)
Expect(res.IsOK()).To(Equal(false), "transaction should have failed")
Expect(
strings.Contains(res.GetLog(),
"provided fee < minimum global fee"),
).To(BeTrue(), res.GetLog())
})
It("should reject transactions with MinGasPrices < gasPrice < baseFee", func() {
gasPrice := sdkmath.NewInt(4)
res := checkTx(privKey, &gasPrice, &msg)
Expect(res.IsOK()).To(Equal(false), "transaction should have failed")
Expect(
strings.Contains(res.GetLog(),
"insufficient fee"),
).To(BeTrue(), res.GetLog())
})
It("should accept transactions with gasPrice >= baseFee", func() {
gasPrice := sdkmath.NewInt(5)
res := deliverTx(privKey, &gasPrice, &msg)
Expect(res.IsOK()).To(Equal(true), "transaction should have succeeded", res.GetLog())
})
})
})
})
Describe("Performing EVM transactions", func() {
type txParams struct {
gasPrice *big.Int
gasFeeCap *big.Int
gasTipCap *big.Int
accesses *ethtypes.AccessList
}
type getprices func() txParams
Context("with BaseFee (feemarket) < MinGasPrices (feemarket param)", func() {
var (
baseFee int64
minGasPrices int64
)
BeforeEach(func() {
baseFee = 10_000_000_000
minGasPrices = baseFee + 30_000_000_000
// Note that the tests run the same transactions with `gasLimit =
// 100000`. With the fee calculation `Fee = (baseFee + tip) * gasLimit`,
// a `minGasPrices = 40_000_000_000` results in `minGlobalFee =
// 4000000000000000`
privKey, _ = setupTestWithContext("1", sdk.NewDec(minGasPrices), sdkmath.NewInt(baseFee))
})
Context("during CheckTx", func() {
DescribeTable("should reject transactions with EffectivePrice < MinGasPrices",
func(malleate getprices) {
p := malleate()
to := tests.GenerateAddress()
msgEthereumTx := buildEthTx(privKey, &to, p.gasPrice, p.gasFeeCap, p.gasTipCap, p.accesses)
res := checkEthTx(privKey, msgEthereumTx)
Expect(res.IsOK()).To(Equal(false), "transaction should have failed")
Expect(
strings.Contains(res.GetLog(),
"provided fee < minimum global fee"),
).To(BeTrue(), res.GetLog())
},
Entry("legacy tx", func() txParams {
return txParams{big.NewInt(minGasPrices - 10_000_000_000), nil, nil, nil}
}),
Entry("dynamic tx with GasFeeCap < MinGasPrices, no gasTipCap", func() txParams {
return txParams{nil, big.NewInt(minGasPrices - 10_000_000_000), big.NewInt(0), &ethtypes.AccessList{}}
}),
Entry("dynamic tx with GasFeeCap < MinGasPrices, max gasTipCap", func() txParams {
// Note that max priority fee per gas can't be higher than the max fee per gas (gasFeeCap), i.e. 30_000_000_000)
return txParams{nil, big.NewInt(minGasPrices - 10_000_000_000), big.NewInt(30_000_000_000), &ethtypes.AccessList{}}
}),
Entry("dynamic tx with GasFeeCap > MinGasPrices, EffectivePrice < MinGasPrices", func() txParams {
return txParams{nil, big.NewInt(minGasPrices + 10_000_000_000), big.NewInt(0), &ethtypes.AccessList{}}
}),
)
DescribeTable("should accept transactions with gasPrice >= MinGasPrices",
func(malleate getprices) {
p := malleate()
to := tests.GenerateAddress()
msgEthereumTx := buildEthTx(privKey, &to, p.gasPrice, p.gasFeeCap, p.gasTipCap, p.accesses)
res := checkEthTx(privKey, msgEthereumTx)
Expect(res.IsOK()).To(Equal(true), "transaction should have succeeded", res.GetLog())
},
Entry("legacy tx", func() txParams {
return txParams{big.NewInt(minGasPrices), nil, nil, nil}
}),
// Note that this tx is not rejected on CheckTx, but not on DeliverTx,
// as the baseFee is set to minGasPrices during DeliverTx when baseFee
// < minGasPrices
Entry("dynamic tx with GasFeeCap > MinGasPrices, EffectivePrice > MinGasPrices", func() txParams {
return txParams{nil, big.NewInt(minGasPrices), big.NewInt(30_000_000_000), &ethtypes.AccessList{}}
}),
)
})
Context("during DeliverTx", func() {
DescribeTable("should reject transactions with gasPrice < MinGasPrices",
func(malleate getprices) {
p := malleate()
to := tests.GenerateAddress()
msgEthereumTx := buildEthTx(privKey, &to, p.gasPrice, p.gasFeeCap, p.gasTipCap, p.accesses)
res := deliverEthTx(privKey, msgEthereumTx)
Expect(res.IsOK()).To(Equal(false), "transaction should have failed")
Expect(
strings.Contains(res.GetLog(),
"provided fee < minimum global fee"),
).To(BeTrue(), res.GetLog())
},
Entry("legacy tx", func() txParams {
return txParams{big.NewInt(minGasPrices - 10_000_000_000), nil, nil, nil}
}),
Entry("dynamic tx with GasFeeCap < MinGasPrices, no gasTipCap", func() txParams {
return txParams{nil, big.NewInt(minGasPrices - 10_000_000_000), big.NewInt(0), &ethtypes.AccessList{}}
}),
Entry("dynamic tx with GasFeeCap < MinGasPrices, max gasTipCap", func() txParams {
// Note that max priority fee per gas can't be higher than the max fee per gas (gasFeeCap), i.e. 30_000_000_000)
return txParams{nil, big.NewInt(minGasPrices - 10_000_000_000), big.NewInt(30_000_000_000), &ethtypes.AccessList{}}
}),
)
DescribeTable("should accept transactions with gasPrice >= MinGasPrices",
func(malleate getprices) {
p := malleate()
to := tests.GenerateAddress()
msgEthereumTx := buildEthTx(privKey, &to, p.gasPrice, p.gasFeeCap, p.gasTipCap, p.accesses)
res := deliverEthTx(privKey, msgEthereumTx)
Expect(res.IsOK()).To(Equal(true), "transaction should have succeeded", res.GetLog())
},
Entry("legacy tx", func() txParams {
return txParams{big.NewInt(minGasPrices + 1), nil, nil, nil}
}),
Entry("dynamic tx, EffectivePrice > MinGasPrices", func() txParams {
return txParams{nil, big.NewInt(minGasPrices + 10_000_000_000), big.NewInt(30_000_000_000), &ethtypes.AccessList{}}
}),
)
})
})
Context("with MinGasPrices (feemarket param) < BaseFee (feemarket)", func() {
var (
baseFee int64
minGasPrices int64
)
BeforeEach(func() {
baseFee = 10_000_000_000
minGasPrices = baseFee - 5_000_000_000
// Note that the tests run the same transactions with `gasLimit =
// 100_000`. With the fee calculation `Fee = (baseFee + tip) * gasLimit`,
// a `minGasPrices = 5_000_000_000` results in `minGlobalFee =
// 500_000_000_000_000`
privKey, _ = setupTestWithContext("1", sdk.NewDec(minGasPrices), sdkmath.NewInt(baseFee))
})
Context("during CheckTx", func() {
DescribeTable("should reject transactions with gasPrice < MinGasPrices",
func(malleate getprices) {
p := malleate()
to := tests.GenerateAddress()
msgEthereumTx := buildEthTx(privKey, &to, p.gasPrice, p.gasFeeCap, p.gasTipCap, p.accesses)
res := checkEthTx(privKey, msgEthereumTx)
Expect(res.IsOK()).To(Equal(false), "transaction should have failed")
Expect(
strings.Contains(res.GetLog(),
"provided fee < minimum global fee"),
).To(BeTrue(), res.GetLog())
},
Entry("legacy tx", func() txParams {
return txParams{big.NewInt(minGasPrices - 1_000_000_000), nil, nil, nil}
}),
Entry("dynamic tx with GasFeeCap < MinGasPrices, no gasTipCap", func() txParams {
return txParams{nil, big.NewInt(minGasPrices - 1_000_000_000), big.NewInt(0), &ethtypes.AccessList{}}
}),
Entry("dynamic tx with GasFeeCap < MinGasPrices, max gasTipCap", func() txParams {
return txParams{nil, big.NewInt(minGasPrices - 1_000_000_000), big.NewInt(minGasPrices - 1_000_000_000), &ethtypes.AccessList{}}
}),
)
DescribeTable("should reject transactions with MinGasPrices < tx gasPrice < EffectivePrice",
func(malleate getprices) {
p := malleate()
to := tests.GenerateAddress()
msgEthereumTx := buildEthTx(privKey, &to, p.gasPrice, p.gasFeeCap, p.gasTipCap, p.accesses)
res := checkEthTx(privKey, msgEthereumTx)
Expect(res.IsOK()).To(Equal(false), "transaction should have failed")
Expect(
strings.Contains(res.GetLog(),
"insufficient fee"),
).To(BeTrue(), res.GetLog())
},
Entry("legacy tx", func() txParams {
return txParams{big.NewInt(baseFee - 1_000_000_000), nil, nil, nil}
}),
Entry("dynamic tx", func() txParams {
return txParams{nil, big.NewInt(baseFee - 1_000_000_000), big.NewInt(0), &ethtypes.AccessList{}}
}),
)
DescribeTable("should accept transactions with gasPrice >= EffectivePrice",
func(malleate getprices) {
p := malleate()
to := tests.GenerateAddress()
msgEthereumTx := buildEthTx(privKey, &to, p.gasPrice, p.gasFeeCap, p.gasTipCap, p.accesses)
res := checkEthTx(privKey, msgEthereumTx)
Expect(res.IsOK()).To(Equal(true), "transaction should have succeeded", res.GetLog())
},
Entry("legacy tx", func() txParams {
return txParams{big.NewInt(baseFee), nil, nil, nil}
}),
Entry("dynamic tx", func() txParams {
return txParams{nil, big.NewInt(baseFee), big.NewInt(0), &ethtypes.AccessList{}}
}),
)
})
Context("during DeliverTx", func() {
DescribeTable("should reject transactions with gasPrice < MinGasPrices",
func(malleate getprices) {
p := malleate()
to := tests.GenerateAddress()
msgEthereumTx := buildEthTx(privKey, &to, p.gasPrice, p.gasFeeCap, p.gasTipCap, p.accesses)
res := deliverEthTx(privKey, msgEthereumTx)
Expect(res.IsOK()).To(Equal(false), "transaction should have failed")
Expect(
strings.Contains(res.GetLog(),
"provided fee < minimum global fee"),
).To(BeTrue(), res.GetLog())
},
Entry("legacy tx", func() txParams {
return txParams{big.NewInt(minGasPrices - 1_000_000_000), nil, nil, nil}
}),
Entry("dynamic tx", func() txParams {
return txParams{nil, big.NewInt(minGasPrices - 1_000_000_000), nil, &ethtypes.AccessList{}}
}),
)
DescribeTable("should reject transactions with MinGasPrices < gasPrice < EffectivePrice",
func(malleate getprices) {
p := malleate()
to := tests.GenerateAddress()
msgEthereumTx := buildEthTx(privKey, &to, p.gasPrice, p.gasFeeCap, p.gasTipCap, p.accesses)
res := deliverEthTx(privKey, msgEthereumTx)
Expect(res.IsOK()).To(Equal(false), "transaction should have failed")
Expect(
strings.Contains(res.GetLog(),
"insufficient fee"),
).To(BeTrue(), res.GetLog())
},
// Note that the baseFee is not 10_000_000_000 anymore but updates to 8_750_000_000 because of the s.Commit
Entry("legacy tx", func() txParams {
return txParams{big.NewInt(baseFee - 2_000_000_000), nil, nil, nil}
}),
Entry("dynamic tx", func() txParams {
return txParams{nil, big.NewInt(baseFee - 2_000_000_000), big.NewInt(0), &ethtypes.AccessList{}}
}),
)
DescribeTable("should accept transactions with gasPrice >= EffectivePrice",
func(malleate getprices) {
p := malleate()
to := tests.GenerateAddress()
msgEthereumTx := buildEthTx(privKey, &to, p.gasPrice, p.gasFeeCap, p.gasTipCap, p.accesses)
res := deliverEthTx(privKey, msgEthereumTx)
Expect(res.IsOK()).To(Equal(true), "transaction should have succeeded", res.GetLog())
},
Entry("legacy tx", func() txParams {
return txParams{big.NewInt(baseFee), nil, nil, nil}
}),
Entry("dynamic tx", func() txParams {
return txParams{nil, big.NewInt(baseFee), big.NewInt(0), &ethtypes.AccessList{}}
}),
)
})
})
})
})
// setupTestWithContext sets up a test chain with an example Cosmos send msg,
// given a local (validator config) and a gloabl (feemarket param) minGasPrice
func setupTestWithContext(valMinGasPrice string, minGasPrice sdk.Dec, baseFee sdkmath.Int) (*ethsecp256k1.PrivKey, banktypes.MsgSend) {
privKey, msg := setupTest(valMinGasPrice + s.denom)
params := types.DefaultParams()
params.MinGasPrice = minGasPrice
s.app.FeeMarketKeeper.SetParams(s.ctx, params)
s.app.FeeMarketKeeper.SetBaseFee(s.ctx, baseFee.BigInt())
s.Commit()
return privKey, msg
}
func setupTest(localMinGasPrices string) (*ethsecp256k1.PrivKey, banktypes.MsgSend) {
setupChain(localMinGasPrices)
privKey, address := generateKey()
amount, ok := sdkmath.NewIntFromString("10000000000000000000")
s.Require().True(ok)
initBalance := sdk.Coins{sdk.Coin{
Denom: s.denom,
Amount: amount,
}}
testutil.FundAccount(s.app.BankKeeper, s.ctx, address, initBalance)
msg := banktypes.MsgSend{
FromAddress: address.String(),
ToAddress: address.String(),
Amount: sdk.Coins{sdk.Coin{
Denom: s.denom,
Amount: sdkmath.NewInt(10000),
}},
}
s.Commit()
return privKey, msg
}
func setupChain(localMinGasPricesStr string) {
// Initialize the app, so we can use SetMinGasPrices to set the
// validator-specific min-gas-prices setting
db := dbm.NewMemDB()
newapp := app.NewEthermintApp(
log.NewNopLogger(),
db,
nil,
true,
map[int64]bool{},
app.DefaultNodeHome,
5,
encoding.MakeConfig(app.ModuleBasics),
simapp.EmptyAppOptions{},
baseapp.SetMinGasPrices(localMinGasPricesStr),
)
genesisState := app.NewTestGenesisState(newapp.AppCodec())
genesisState[types.ModuleName] = newapp.AppCodec().MustMarshalJSON(types.DefaultGenesisState())
stateBytes, err := json.MarshalIndent(genesisState, "", " ")
s.Require().NoError(err)
// Initialize the chain
newapp.InitChain(
abci.RequestInitChain{
ChainId: "ethermint_9000-1",
Validators: []abci.ValidatorUpdate{},
AppStateBytes: stateBytes,
ConsensusParams: app.DefaultConsensusParams,
},
)
s.app = newapp
s.SetupApp(false)
}
func generateKey() (*ethsecp256k1.PrivKey, sdk.AccAddress) {
address, priv := tests.NewAddrKey()
return priv.(*ethsecp256k1.PrivKey), sdk.AccAddress(address.Bytes())
}
func getNonce(addressBytes []byte) uint64 {
return s.app.EvmKeeper.GetNonce(
s.ctx,
common.BytesToAddress(addressBytes),
)
}
func buildEthTx(
priv *ethsecp256k1.PrivKey,
to *common.Address,
gasPrice *big.Int,
gasFeeCap *big.Int,
gasTipCap *big.Int,
accesses *ethtypes.AccessList,
) *evmtypes.MsgEthereumTx {
chainID := s.app.EvmKeeper.ChainID()
from := common.BytesToAddress(priv.PubKey().Address().Bytes())
nonce := getNonce(from.Bytes())
data := make([]byte, 0)
gasLimit := uint64(100000)
msgEthereumTx := evmtypes.NewTx(
chainID,
nonce,
to,
nil,
gasLimit,
gasPrice,
gasFeeCap,
gasTipCap,
data,
accesses,
)
msgEthereumTx.From = from.String()
return msgEthereumTx
}
func prepareEthTx(priv *ethsecp256k1.PrivKey, msgEthereumTx *evmtypes.MsgEthereumTx) []byte {
encodingConfig := encoding.MakeConfig(app.ModuleBasics)
option, err := codectypes.NewAnyWithValue(&evmtypes.ExtensionOptionsEthereumTx{})
s.Require().NoError(err)
txBuilder := encodingConfig.TxConfig.NewTxBuilder()
builder, ok := txBuilder.(authtx.ExtensionOptionsTxBuilder)
s.Require().True(ok)
builder.SetExtensionOptions(option)
err = msgEthereumTx.Sign(s.ethSigner, tests.NewSigner(priv))
s.Require().NoError(err)
msgEthereumTx.From = ""
err = txBuilder.SetMsgs(msgEthereumTx)
s.Require().NoError(err)
txData, err := evmtypes.UnpackTxData(msgEthereumTx.Data)
s.Require().NoError(err)
evmDenom := s.app.EvmKeeper.GetParams(s.ctx).EvmDenom
fees := sdk.Coins{{Denom: evmDenom, Amount: sdkmath.NewIntFromBigInt(txData.Fee())}}
builder.SetFeeAmount(fees)
builder.SetGasLimit(msgEthereumTx.GetGas())
// bz are bytes to be broadcasted over the network
bz, err := encodingConfig.TxConfig.TxEncoder()(txBuilder.GetTx())
s.Require().NoError(err)
return bz
}
func checkEthTx(priv *ethsecp256k1.PrivKey, msgEthereumTx *evmtypes.MsgEthereumTx) abci.ResponseCheckTx {
bz := prepareEthTx(priv, msgEthereumTx)
req := abci.RequestCheckTx{Tx: bz}
res := s.app.BaseApp.CheckTx(req)
return res
}
func deliverEthTx(priv *ethsecp256k1.PrivKey, msgEthereumTx *evmtypes.MsgEthereumTx) abci.ResponseDeliverTx {
bz := prepareEthTx(priv, msgEthereumTx)
req := abci.RequestDeliverTx{Tx: bz}
res := s.app.BaseApp.DeliverTx(req)
return res
}
func prepareCosmosTx(priv *ethsecp256k1.PrivKey, gasPrice *sdkmath.Int, msgs ...sdk.Msg) []byte {
encodingConfig := encoding.MakeConfig(app.ModuleBasics)
accountAddress := sdk.AccAddress(priv.PubKey().Address().Bytes())
txBuilder := encodingConfig.TxConfig.NewTxBuilder()
txBuilder.SetGasLimit(1000000)
if gasPrice == nil {
_gasPrice := sdkmath.NewInt(1)
gasPrice = &_gasPrice
}
fees := &sdk.Coins{{Denom: s.denom, Amount: gasPrice.MulRaw(1000000)}}
txBuilder.SetFeeAmount(*fees)
err := txBuilder.SetMsgs(msgs...)
s.Require().NoError(err)
seq, err := s.app.AccountKeeper.GetSequence(s.ctx, accountAddress)
s.Require().NoError(err)
// First round: we gather all the signer infos. We use the "set empty
// signature" hack to do that.
sigV2 := signing.SignatureV2{
PubKey: priv.PubKey(),
Data: &signing.SingleSignatureData{
SignMode: encodingConfig.TxConfig.SignModeHandler().DefaultMode(),
Signature: nil,
},
Sequence: seq,
}
sigsV2 := []signing.SignatureV2{sigV2}
err = txBuilder.SetSignatures(sigsV2...)
s.Require().NoError(err)
// Second round: all signer infos are set, so each signer can sign.
accNumber := s.app.AccountKeeper.GetAccount(s.ctx, accountAddress).GetAccountNumber()
signerData := authsigning.SignerData{
ChainID: s.ctx.ChainID(),
AccountNumber: accNumber,
Sequence: seq,
}
sigV2, err = tx.SignWithPrivKey(
encodingConfig.TxConfig.SignModeHandler().DefaultMode(), signerData,
txBuilder, priv, encodingConfig.TxConfig,
seq,
)
s.Require().NoError(err)
sigsV2 = []signing.SignatureV2{sigV2}
err = txBuilder.SetSignatures(sigsV2...)
s.Require().NoError(err)
// bz are bytes to be broadcasted over the network
bz, err := encodingConfig.TxConfig.TxEncoder()(txBuilder.GetTx())
s.Require().NoError(err)
return bz
}
func checkTx(priv *ethsecp256k1.PrivKey, gasPrice *sdkmath.Int, msgs ...sdk.Msg) abci.ResponseCheckTx {
bz := prepareCosmosTx(priv, gasPrice, msgs...)
req := abci.RequestCheckTx{Tx: bz}
res := s.app.BaseApp.CheckTx(req)
return res
}
func deliverTx(priv *ethsecp256k1.PrivKey, gasPrice *sdkmath.Int, msgs ...sdk.Msg) abci.ResponseDeliverTx {
bz := prepareCosmosTx(priv, gasPrice, msgs...)
req := abci.RequestDeliverTx{Tx: bz}
res := s.app.BaseApp.DeliverTx(req)
return res
}
+54 -14
View File
@@ -1,13 +1,16 @@
package keeper
import (
"math/big"
"github.com/cosmos/cosmos-sdk/codec"
storetypes "github.com/cosmos/cosmos-sdk/store/types"
sdk "github.com/cosmos/cosmos-sdk/types"
paramtypes "github.com/cosmos/cosmos-sdk/x/params/types"
"github.com/tendermint/tendermint/libs/log"
v010 "github.com/cerc-io/laconicd/x/feemarket/migrations/v010"
"github.com/cerc-io/laconicd/x/feemarket/types"
storetypes "github.com/cosmos/cosmos-sdk/store/types"
)
// Keeper grants access to the Fee Market module state.
@@ -15,14 +18,15 @@ type Keeper struct {
// Protobuf codec
cdc codec.BinaryCodec
// Store key required for the Fee Market Prefix KVStore.
storeKey storetypes.StoreKey
storeKey storetypes.StoreKey
transientKey storetypes.StoreKey
// module specific parameter space that can be configured through governance
paramSpace paramtypes.Subspace
}
// NewKeeper generates new fee market module keeper
func NewKeeper(
cdc codec.BinaryCodec, storeKey storetypes.StoreKey, paramSpace paramtypes.Subspace,
cdc codec.BinaryCodec, paramSpace paramtypes.Subspace, storeKey, transientKey storetypes.StoreKey,
) Keeper {
// set KeyTable if it has not already been set
if !paramSpace.HasKeyTable() {
@@ -30,9 +34,10 @@ func NewKeeper(
}
return Keeper{
cdc: cdc,
storeKey: storeKey,
paramSpace: paramSpace,
cdc: cdc,
storeKey: storeKey,
paramSpace: paramSpace,
transientKey: transientKey,
}
}
@@ -46,10 +51,18 @@ func (k Keeper) Logger(ctx sdk.Context) log.Logger {
// Required by EIP1559 base fee calculation.
// ----------------------------------------------------------------------------
// GetBlockGasUsed returns the last block gas used value from the store.
func (k Keeper) GetBlockGasUsed(ctx sdk.Context) uint64 {
// SetBlockGasWanted sets the block gas wanted to the store.
// CONTRACT: this should be only called during EndBlock.
func (k Keeper) SetBlockGasWanted(ctx sdk.Context, gas uint64) {
store := ctx.KVStore(k.storeKey)
bz := store.Get(types.KeyPrefixBlockGasUsed)
gasBz := sdk.Uint64ToBigEndian(gas)
store.Set(types.KeyPrefixBlockGasWanted, gasBz)
}
// GetBlockGasWanted returns the last block gas wanted value from the store.
func (k Keeper) GetBlockGasWanted(ctx sdk.Context) uint64 {
store := ctx.KVStore(k.storeKey)
bz := store.Get(types.KeyPrefixBlockGasWanted)
if len(bz) == 0 {
return 0
}
@@ -57,10 +70,37 @@ func (k Keeper) GetBlockGasUsed(ctx sdk.Context) uint64 {
return sdk.BigEndianToUint64(bz)
}
// SetBlockGasUsed gets the block gas consumed to the store.
// CONTRACT: this should be only called during EndBlock.
func (k Keeper) SetBlockGasUsed(ctx sdk.Context, gas uint64) {
// GetTransientGasWanted returns the gas wanted in the current block from transient store.
func (k Keeper) GetTransientGasWanted(ctx sdk.Context) uint64 {
store := ctx.TransientStore(k.transientKey)
bz := store.Get(types.KeyPrefixTransientBlockGasWanted)
if len(bz) == 0 {
return 0
}
return sdk.BigEndianToUint64(bz)
}
// SetTransientBlockGasWanted sets the block gas wanted to the transient store.
func (k Keeper) SetTransientBlockGasWanted(ctx sdk.Context, gasWanted uint64) {
store := ctx.TransientStore(k.transientKey)
gasBz := sdk.Uint64ToBigEndian(gasWanted)
store.Set(types.KeyPrefixTransientBlockGasWanted, gasBz)
}
// AddTransientGasWanted adds the cumulative gas wanted in the transient store
func (k Keeper) AddTransientGasWanted(ctx sdk.Context, gasWanted uint64) (uint64, error) {
result := k.GetTransientGasWanted(ctx) + gasWanted
k.SetTransientBlockGasWanted(ctx, result)
return result, nil
}
// GetBaseFeeV1 get the base fee from v1 version of states.
// return nil if base fee is not enabled
func (k Keeper) GetBaseFeeV1(ctx sdk.Context) *big.Int {
store := ctx.KVStore(k.storeKey)
gasBz := sdk.Uint64ToBigEndian(gas)
store.Set(types.KeyPrefixBlockGasUsed, gasBz)
bz := store.Get(v010.KeyPrefixBaseFeeV1)
if len(bz) == 0 {
return nil
}
return new(big.Int).SetBytes(bz)
}
+71 -17
View File
@@ -6,26 +6,34 @@ import (
"testing"
"time"
. "github.com/onsi/ginkgo/v2"
. "github.com/onsi/gomega"
"github.com/stretchr/testify/require"
"github.com/stretchr/testify/suite"
"github.com/cerc-io/laconicd/app"
"github.com/cerc-io/laconicd/crypto/ethsecp256k1"
"github.com/cerc-io/laconicd/encoding"
"github.com/cerc-io/laconicd/tests"
ethermint "github.com/cerc-io/laconicd/types"
"github.com/cerc-io/laconicd/x/feemarket/types"
"github.com/cosmos/cosmos-sdk/baseapp"
"github.com/cosmos/cosmos-sdk/client"
"github.com/cosmos/cosmos-sdk/codec"
"github.com/cosmos/cosmos-sdk/crypto/keyring"
sdk "github.com/cosmos/cosmos-sdk/types"
authtypes "github.com/cosmos/cosmos-sdk/x/auth/types"
stakingkeeper "github.com/cosmos/cosmos-sdk/x/staking/keeper"
stakingtypes "github.com/cosmos/cosmos-sdk/x/staking/types"
"github.com/cerc-io/laconicd/app"
"github.com/cerc-io/laconicd/crypto/ethsecp256k1"
"github.com/cerc-io/laconicd/encoding"
"github.com/cerc-io/laconicd/tests"
ethermint "github.com/cerc-io/laconicd/types"
evmtypes "github.com/cerc-io/laconicd/x/evm/types"
"github.com/cerc-io/laconicd/x/feemarket/types"
"github.com/ethereum/go-ethereum/common"
ethtypes "github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/crypto"
abci "github.com/tendermint/tendermint/abci/types"
"github.com/tendermint/tendermint/crypto/tmhash"
tmproto "github.com/tendermint/tendermint/proto/tendermint/types"
tmversion "github.com/tendermint/tendermint/proto/tendermint/version"
@@ -47,12 +55,29 @@ type KeeperTestSuite struct {
appCodec codec.Codec
signer keyring.Signer
denom string
}
/// DoSetupTest setup test environment, it uses`require.TestingT` to support both `testing.T` and `testing.B`.
func (suite *KeeperTestSuite) DoSetupTest(t require.TestingT) {
checkTx := false
var s *KeeperTestSuite
func TestKeeperTestSuite(t *testing.T) {
s = new(KeeperTestSuite)
suite.Run(t, s)
// Run Ginkgo integration tests
RegisterFailHandler(Fail)
RunSpecs(t, "Keeper Suite")
}
// SetupTest setup test environment, it uses`require.TestingT` to support both `testing.T` and `testing.B`.
func (suite *KeeperTestSuite) SetupTest() {
checkTx := false
suite.app = app.Setup(checkTx, nil)
suite.SetupApp(checkTx)
}
func (suite *KeeperTestSuite) SetupApp(checkTx bool) {
t := suite.T()
// account key
priv, err := ethsecp256k1.GenerateKey()
require.NoError(t, err)
@@ -64,7 +89,6 @@ func (suite *KeeperTestSuite) DoSetupTest(t require.TestingT) {
require.NoError(t, err)
suite.consAddress = sdk.ConsAddress(priv.PubKey().Address())
suite.app = app.Setup(suite.T(), checkTx, nil)
suite.ctx = suite.app.BaseApp.NewContext(checkTx, tmproto.Header{
Height: 1,
ChainID: "ethermint_9000-1",
@@ -99,21 +123,51 @@ func (suite *KeeperTestSuite) DoSetupTest(t require.TestingT) {
}
suite.app.AccountKeeper.SetAccount(suite.ctx, acc)
valAddr := sdk.ValAddress(suite.address.Bytes())
validator, err := stakingtypes.NewValidator(valAddr, priv.PubKey(), stakingtypes.Description{})
require.NoError(t, err)
validator = stakingkeeper.TestingUpdateValidator(suite.app.StakingKeeper, suite.ctx, validator, true)
err = suite.app.StakingKeeper.AfterValidatorCreated(suite.ctx, validator.GetOperator())
require.NoError(t, err)
err = suite.app.StakingKeeper.SetValidatorByConsAddr(suite.ctx, validator)
require.NoError(t, err)
suite.app.StakingKeeper.SetValidator(suite.ctx, validator)
encodingConfig := encoding.MakeConfig(app.ModuleBasics)
suite.clientCtx = client.Context{}.WithTxConfig(encodingConfig.TxConfig)
suite.ethSigner = ethtypes.LatestSignerForChainID(suite.app.EvmKeeper.ChainID())
suite.appCodec = encodingConfig.Codec
suite.denom = evmtypes.DefaultEVMDenom
}
func (suite *KeeperTestSuite) SetupTest() {
suite.DoSetupTest(suite.T())
// Commit commits and starts a new block with an updated context.
func (suite *KeeperTestSuite) Commit() {
suite.CommitAfter(time.Second * 0)
}
func TestKeeperTestSuite(t *testing.T) {
suite.Run(t, new(KeeperTestSuite))
// Commit commits a block at a given time.
func (suite *KeeperTestSuite) CommitAfter(t time.Duration) {
header := suite.ctx.BlockHeader()
suite.app.EndBlock(abci.RequestEndBlock{Height: header.Height})
_ = suite.app.Commit()
header.Height += 1
header.Time = header.Time.Add(t)
suite.app.BeginBlock(abci.RequestBeginBlock{
Header: header,
})
// update ctx
suite.ctx = suite.app.BaseApp.NewContext(false, header)
queryHelper := baseapp.NewQueryServerTestHelper(suite.ctx, suite.app.InterfaceRegistry())
types.RegisterQueryServer(queryHelper, suite.app.FeeMarketKeeper)
suite.queryClient = types.NewQueryClient(queryHelper)
}
func (suite *KeeperTestSuite) TestSetGetBlockGasUsed() {
func (suite *KeeperTestSuite) TestSetGetBlockGasWanted() {
testCases := []struct {
name string
malleate func()
@@ -122,7 +176,7 @@ func (suite *KeeperTestSuite) TestSetGetBlockGasUsed() {
{
"with last block given",
func() {
suite.app.FeeMarketKeeper.SetBlockGasUsed(suite.ctx, uint64(1000000))
suite.app.FeeMarketKeeper.SetBlockGasWanted(suite.ctx, uint64(1000000))
},
uint64(1000000),
},
@@ -130,7 +184,7 @@ func (suite *KeeperTestSuite) TestSetGetBlockGasUsed() {
for _, tc := range testCases {
tc.malleate()
gas := suite.app.FeeMarketKeeper.GetBlockGasUsed(suite.ctx)
gas := suite.app.FeeMarketKeeper.GetBlockGasWanted(suite.ctx)
suite.Require().Equal(tc.expGas, gas, tc.name)
}
}
+6
View File
@@ -4,6 +4,7 @@ import (
sdk "github.com/cosmos/cosmos-sdk/types"
v010 "github.com/cerc-io/laconicd/x/feemarket/migrations/v010"
v011 "github.com/cerc-io/laconicd/x/feemarket/migrations/v011"
)
// Migrator is a struct for handling in-place store migrations.
@@ -22,3 +23,8 @@ func NewMigrator(keeper Keeper) Migrator {
func (m Migrator) Migrate1to2(ctx sdk.Context) error {
return v010.MigrateStore(ctx, &m.keeper.paramSpace, m.keeper.storeKey)
}
// Migrate2to3 migrates the store from consensus version v2 to v3
func (m Migrator) Migrate2to3(ctx sdk.Context) error {
return v011.MigrateStore(ctx, &m.keeper.paramSpace)
}
+14 -3
View File
@@ -3,13 +3,18 @@ package keeper
import (
"math/big"
sdkmath "cosmossdk.io/math"
"github.com/cerc-io/laconicd/x/feemarket/types"
sdk "github.com/cosmos/cosmos-sdk/types"
)
// GetParams returns the total set of fee market parameters.
func (k Keeper) GetParams(ctx sdk.Context) (params types.Params) {
k.paramSpace.GetParamSet(ctx, &params)
// TODO: update once https://github.com/cosmos/cosmos-sdk/pull/12615 is merged
// and released
for _, pair := range params.ParamSetPairs() {
k.paramSpace.GetIfExists(ctx, pair.Key, pair.Value)
}
return params
}
@@ -31,10 +36,16 @@ func (k Keeper) GetBaseFee(ctx sdk.Context) *big.Int {
return nil
}
return params.BaseFee.BigInt()
baseFee := params.BaseFee.BigInt()
if baseFee == nil || baseFee.Sign() == 0 {
// try v1 format
return k.GetBaseFeeV1(ctx)
}
return baseFee
}
// SetBaseFee set's the base fee in the paramSpace
func (k Keeper) SetBaseFee(ctx sdk.Context, baseFee *big.Int) {
k.paramSpace.Set(ctx, types.ParamStoreKeyBaseFee, sdk.NewIntFromBigInt(baseFee))
k.paramSpace.Set(ctx, types.ParamStoreKeyBaseFee, sdkmath.NewIntFromBigInt(baseFee))
}
+4 -3
View File
@@ -3,11 +3,12 @@ package v010
import (
"math/big"
sdkmath "cosmossdk.io/math"
storetypes "github.com/cosmos/cosmos-sdk/store/types"
sdk "github.com/cosmos/cosmos-sdk/types"
"github.com/cerc-io/laconicd/x/feemarket/migrations/v010/types"
v09types "github.com/cerc-io/laconicd/x/feemarket/migrations/v09/types"
"github.com/cerc-io/laconicd/x/feemarket/types"
storetypes "github.com/cosmos/cosmos-sdk/store/types"
paramtypes "github.com/cosmos/cosmos-sdk/x/params/types"
)
@@ -29,7 +30,7 @@ func MigrateStore(ctx sdk.Context, paramstore *paramtypes.Subspace, storeKey sto
switch {
case store.Has(KeyPrefixBaseFeeV1):
bz := store.Get(KeyPrefixBaseFeeV1)
baseFee = sdk.NewIntFromBigInt(new(big.Int).SetBytes(bz))
baseFee = sdkmath.NewIntFromBigInt(new(big.Int).SetBytes(bz))
case paramstore.Has(ctx, types.ParamStoreKeyNoBaseFee):
paramstore.GetIfExists(ctx, types.ParamStoreKeyBaseFee, &baseFee)
}
+26 -2
View File
@@ -1,6 +1,7 @@
package v010_test
import (
"fmt"
"testing"
"github.com/stretchr/testify/require"
@@ -14,6 +15,7 @@ import (
"github.com/cerc-io/laconicd/app"
feemarketkeeper "github.com/cerc-io/laconicd/x/feemarket/keeper"
v010 "github.com/cerc-io/laconicd/x/feemarket/migrations/v010"
v09types "github.com/cerc-io/laconicd/x/feemarket/migrations/v09/types"
"github.com/cerc-io/laconicd/x/feemarket/types"
feemarkettypes "github.com/cerc-io/laconicd/x/feemarket/types"
)
@@ -21,12 +23,12 @@ import (
func TestMigrateStore(t *testing.T) {
encCfg := encoding.MakeConfig(app.ModuleBasics)
feemarketKey := sdk.NewKVStoreKey(feemarkettypes.StoreKey)
tFeeMarketKey := sdk.NewTransientStoreKey("margetkey_test")
tFeeMarketKey := sdk.NewTransientStoreKey(fmt.Sprintf("%s_test", feemarkettypes.StoreKey))
ctx := testutil.DefaultContext(feemarketKey, tFeeMarketKey)
paramstore := paramtypes.NewSubspace(
encCfg.Codec, encCfg.Amino, feemarketKey, tFeeMarketKey, "feemarket",
)
fmKeeper := feemarketkeeper.NewKeeper(encCfg.Codec, feemarketKey, paramstore)
fmKeeper := feemarketkeeper.NewKeeper(encCfg.Codec, paramstore, feemarketKey, tFeeMarketKey)
fmKeeper.SetParams(ctx, types.DefaultParams())
require.True(t, paramstore.HasKeyTable())
@@ -43,3 +45,25 @@ func TestMigrateStore(t *testing.T) {
require.Equal(t, baseFee.Int64(), params.BaseFee.Int64())
}
func TestMigrateJSON(t *testing.T) {
rawJson := `{
"base_fee": "669921875",
"block_gas": "0",
"params": {
"base_fee_change_denominator": 8,
"elasticity_multiplier": 2,
"enable_height": "0",
"initial_base_fee": "1000000000",
"no_base_fee": false
}
}`
encCfg := encoding.MakeConfig(app.ModuleBasics)
var genState v09types.GenesisState
err := encCfg.Codec.UnmarshalJSON([]byte(rawJson), &genState)
require.NoError(t, err)
migratedGenState := v010.MigrateJSON(genState)
require.Equal(t, int64(669921875), migratedGenState.Params.BaseFee.Int64())
}
+472
View File
@@ -0,0 +1,472 @@
// Code generated by protoc-gen-gogo. DO NOT EDIT.
// source: ethermint/feemarket/v1/feemarket.proto
package types
import (
fmt "fmt"
github_com_cosmos_cosmos_sdk_types "github.com/cosmos/cosmos-sdk/types"
_ "github.com/gogo/protobuf/gogoproto"
proto "github.com/gogo/protobuf/proto"
io "io"
math "math"
math_bits "math/bits"
)
// Reference imports to suppress errors if they are not otherwise used.
var _ = proto.Marshal
var _ = fmt.Errorf
var _ = math.Inf
// This is a compile-time assertion to ensure that this generated file
// is compatible with the proto package it is being compiled against.
// A compilation error at this line likely means your copy of the
// proto package needs to be updated.
const _ = proto.GoGoProtoPackageIsVersion3 // please upgrade the proto package
// Params defines the EVM module parameters
type Params struct {
// no base fee forces the EIP-1559 base fee to 0 (needed for 0 price calls)
NoBaseFee bool `protobuf:"varint,1,opt,name=no_base_fee,json=noBaseFee,proto3" json:"no_base_fee,omitempty"`
// base fee change denominator bounds the amount the base fee can change
// between blocks.
BaseFeeChangeDenominator uint32 `protobuf:"varint,2,opt,name=base_fee_change_denominator,json=baseFeeChangeDenominator,proto3" json:"base_fee_change_denominator,omitempty"`
// elasticity multiplier bounds the maximum gas limit an EIP-1559 block may
// have.
ElasticityMultiplier uint32 `protobuf:"varint,3,opt,name=elasticity_multiplier,json=elasticityMultiplier,proto3" json:"elasticity_multiplier,omitempty"`
// height at which the base fee calculation is enabled.
EnableHeight int64 `protobuf:"varint,5,opt,name=enable_height,json=enableHeight,proto3" json:"enable_height,omitempty"`
// base fee for EIP-1559 blocks.
BaseFee github_com_cosmos_cosmos_sdk_types.Int `protobuf:"bytes,6,opt,name=base_fee,json=baseFee,proto3,customtype=github.com/cosmos/cosmos-sdk/types.Int" json:"base_fee"`
}
func (m *Params) Reset() { *m = Params{} }
func (m *Params) String() string { return proto.CompactTextString(m) }
func (*Params) ProtoMessage() {}
func (*Params) Descriptor() ([]byte, []int) {
return fileDescriptor_4feb8b20cf98e6e1, []int{0}
}
func (m *Params) XXX_Unmarshal(b []byte) error {
return m.Unmarshal(b)
}
func (m *Params) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
if deterministic {
return xxx_messageInfo_Params.Marshal(b, m, deterministic)
} else {
b = b[:cap(b)]
n, err := m.MarshalToSizedBuffer(b)
if err != nil {
return nil, err
}
return b[:n], nil
}
}
func (m *Params) XXX_Merge(src proto.Message) {
xxx_messageInfo_Params.Merge(m, src)
}
func (m *Params) XXX_Size() int {
return m.Size()
}
func (m *Params) XXX_DiscardUnknown() {
xxx_messageInfo_Params.DiscardUnknown(m)
}
var xxx_messageInfo_Params proto.InternalMessageInfo
func (m *Params) GetNoBaseFee() bool {
if m != nil {
return m.NoBaseFee
}
return false
}
func (m *Params) GetBaseFeeChangeDenominator() uint32 {
if m != nil {
return m.BaseFeeChangeDenominator
}
return 0
}
func (m *Params) GetElasticityMultiplier() uint32 {
if m != nil {
return m.ElasticityMultiplier
}
return 0
}
func (m *Params) GetEnableHeight() int64 {
if m != nil {
return m.EnableHeight
}
return 0
}
var fileDescriptor_4feb8b20cf98e6e1 = []byte{
// 343 bytes of a gzipped FileDescriptorProto
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x4c, 0x91, 0xcf, 0x6a, 0xea, 0x40,
0x14, 0x87, 0x33, 0xfe, 0xbb, 0x9a, 0x7b, 0x05, 0x09, 0xde, 0x4b, 0xb8, 0x85, 0x18, 0x5a, 0x90,
0x6c, 0x9a, 0x20, 0xae, 0xbb, 0xb1, 0xa5, 0x68, 0xa1, 0x50, 0xb2, 0xec, 0x26, 0x4c, 0xe2, 0x31,
0x19, 0x4c, 0x66, 0x64, 0xe6, 0x28, 0xf5, 0x2d, 0xfa, 0x10, 0x7d, 0x18, 0x97, 0x2e, 0x4b, 0x17,
0x52, 0xf4, 0x45, 0x4a, 0xa3, 0x4d, 0x5c, 0xcd, 0xcc, 0xf9, 0xbe, 0xe1, 0x1c, 0xce, 0x4f, 0xef,
0x03, 0x26, 0x20, 0x33, 0xc6, 0xd1, 0x9b, 0x01, 0x64, 0x54, 0xce, 0x01, 0xbd, 0xd5, 0xa0, 0x7c,
0xb8, 0x0b, 0x29, 0x50, 0x18, 0xff, 0x0a, 0xcf, 0x2d, 0xd1, 0x6a, 0xf0, 0xbf, 0x1b, 0x8b, 0x58,
0xe4, 0x8a, 0xf7, 0x7d, 0x3b, 0xda, 0x97, 0x6f, 0x15, 0xbd, 0xf1, 0x44, 0x25, 0xcd, 0x94, 0x61,
0xe9, 0xbf, 0xb9, 0x08, 0x42, 0xaa, 0x20, 0x98, 0x01, 0x98, 0xc4, 0x26, 0x4e, 0xd3, 0x6f, 0x71,
0x31, 0xa2, 0x0a, 0xee, 0x01, 0x8c, 0x1b, 0xfd, 0xe2, 0x07, 0x06, 0x51, 0x42, 0x79, 0x0c, 0xc1,
0x14, 0xb8, 0xc8, 0x18, 0xa7, 0x28, 0xa4, 0x59, 0xb1, 0x89, 0xd3, 0xf6, 0xcd, 0xf0, 0x68, 0xdf,
0xe6, 0xc2, 0x5d, 0xc9, 0x8d, 0xa1, 0xfe, 0x17, 0x52, 0xaa, 0x90, 0x45, 0x0c, 0xd7, 0x41, 0xb6,
0x4c, 0x91, 0x2d, 0x52, 0x06, 0xd2, 0xac, 0xe6, 0x1f, 0xbb, 0x25, 0x7c, 0x2c, 0x98, 0x71, 0xa5,
0xb7, 0x81, 0xd3, 0x30, 0x85, 0x20, 0x01, 0x16, 0x27, 0x68, 0xd6, 0x6d, 0xe2, 0x54, 0xfd, 0x3f,
0xc7, 0xe2, 0x38, 0xaf, 0x19, 0x13, 0xbd, 0x59, 0x4c, 0xdd, 0xb0, 0x89, 0xd3, 0x1a, 0xb9, 0x9b,
0x5d, 0x4f, 0xfb, 0xd8, 0xf5, 0xfa, 0x31, 0xc3, 0x64, 0x19, 0xba, 0x91, 0xc8, 0xbc, 0x48, 0xa8,
0x4c, 0xa8, 0xd3, 0x71, 0xad, 0xa6, 0x73, 0x0f, 0xd7, 0x0b, 0x50, 0xee, 0x84, 0xa3, 0xff, 0xeb,
0x34, 0xf5, 0x43, 0xad, 0x59, 0xeb, 0xd4, 0xfd, 0x0e, 0xe3, 0x0c, 0x19, 0x4d, 0x8b, 0x65, 0x8c,
0xc6, 0x9b, 0xbd, 0x45, 0xb6, 0x7b, 0x8b, 0x7c, 0xee, 0x2d, 0xf2, 0x7a, 0xb0, 0xb4, 0xed, 0xc1,
0xd2, 0xde, 0x0f, 0x96, 0xf6, 0xec, 0x9e, 0xb5, 0xc0, 0x84, 0x4a, 0xc5, 0x94, 0x57, 0x26, 0xf5,
0x72, 0x96, 0x55, 0xde, 0x2e, 0x6c, 0xe4, 0x7b, 0x1f, 0x7e, 0x05, 0x00, 0x00, 0xff, 0xff, 0xee,
0xfc, 0x5c, 0x06, 0xcf, 0x01, 0x00, 0x00,
}
func (m *Params) Marshal() (dAtA []byte, err error) {
size := m.Size()
dAtA = make([]byte, size)
n, err := m.MarshalToSizedBuffer(dAtA[:size])
if err != nil {
return nil, err
}
return dAtA[:n], nil
}
func (m *Params) MarshalTo(dAtA []byte) (int, error) {
size := m.Size()
return m.MarshalToSizedBuffer(dAtA[:size])
}
func (m *Params) MarshalToSizedBuffer(dAtA []byte) (int, error) {
i := len(dAtA)
_ = i
var l int
_ = l
{
size := m.BaseFee.Size()
i -= size
if _, err := m.BaseFee.MarshalTo(dAtA[i:]); err != nil {
return 0, err
}
i = encodeVarintFeemarket(dAtA, i, uint64(size))
}
i--
dAtA[i] = 0x32
if m.EnableHeight != 0 {
i = encodeVarintFeemarket(dAtA, i, uint64(m.EnableHeight))
i--
dAtA[i] = 0x28
}
if m.ElasticityMultiplier != 0 {
i = encodeVarintFeemarket(dAtA, i, uint64(m.ElasticityMultiplier))
i--
dAtA[i] = 0x18
}
if m.BaseFeeChangeDenominator != 0 {
i = encodeVarintFeemarket(dAtA, i, uint64(m.BaseFeeChangeDenominator))
i--
dAtA[i] = 0x10
}
if m.NoBaseFee {
i--
if m.NoBaseFee {
dAtA[i] = 1
} else {
dAtA[i] = 0
}
i--
dAtA[i] = 0x8
}
return len(dAtA) - i, nil
}
func encodeVarintFeemarket(dAtA []byte, offset int, v uint64) int {
offset -= sovFeemarket(v)
base := offset
for v >= 1<<7 {
dAtA[offset] = uint8(v&0x7f | 0x80)
v >>= 7
offset++
}
dAtA[offset] = uint8(v)
return base
}
func (m *Params) Size() (n int) {
if m == nil {
return 0
}
var l int
_ = l
if m.NoBaseFee {
n += 2
}
if m.BaseFeeChangeDenominator != 0 {
n += 1 + sovFeemarket(uint64(m.BaseFeeChangeDenominator))
}
if m.ElasticityMultiplier != 0 {
n += 1 + sovFeemarket(uint64(m.ElasticityMultiplier))
}
if m.EnableHeight != 0 {
n += 1 + sovFeemarket(uint64(m.EnableHeight))
}
l = m.BaseFee.Size()
n += 1 + l + sovFeemarket(uint64(l))
return n
}
func sovFeemarket(x uint64) (n int) {
return (math_bits.Len64(x|1) + 6) / 7
}
func sozFeemarket(x uint64) (n int) {
return sovFeemarket(uint64((x << 1) ^ uint64((int64(x) >> 63))))
}
func (m *Params) Unmarshal(dAtA []byte) error {
l := len(dAtA)
iNdEx := 0
for iNdEx < l {
preIndex := iNdEx
var wire uint64
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return ErrIntOverflowFeemarket
}
if iNdEx >= l {
return io.ErrUnexpectedEOF
}
b := dAtA[iNdEx]
iNdEx++
wire |= uint64(b&0x7F) << shift
if b < 0x80 {
break
}
}
fieldNum := int32(wire >> 3)
wireType := int(wire & 0x7)
if wireType == 4 {
return fmt.Errorf("proto: Params: wiretype end group for non-group")
}
if fieldNum <= 0 {
return fmt.Errorf("proto: Params: illegal tag %d (wire type %d)", fieldNum, wire)
}
switch fieldNum {
case 1:
if wireType != 0 {
return fmt.Errorf("proto: wrong wireType = %d for field NoBaseFee", wireType)
}
var v int
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return ErrIntOverflowFeemarket
}
if iNdEx >= l {
return io.ErrUnexpectedEOF
}
b := dAtA[iNdEx]
iNdEx++
v |= int(b&0x7F) << shift
if b < 0x80 {
break
}
}
m.NoBaseFee = bool(v != 0)
case 2:
if wireType != 0 {
return fmt.Errorf("proto: wrong wireType = %d for field BaseFeeChangeDenominator", wireType)
}
m.BaseFeeChangeDenominator = 0
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return ErrIntOverflowFeemarket
}
if iNdEx >= l {
return io.ErrUnexpectedEOF
}
b := dAtA[iNdEx]
iNdEx++
m.BaseFeeChangeDenominator |= uint32(b&0x7F) << shift
if b < 0x80 {
break
}
}
case 3:
if wireType != 0 {
return fmt.Errorf("proto: wrong wireType = %d for field ElasticityMultiplier", wireType)
}
m.ElasticityMultiplier = 0
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return ErrIntOverflowFeemarket
}
if iNdEx >= l {
return io.ErrUnexpectedEOF
}
b := dAtA[iNdEx]
iNdEx++
m.ElasticityMultiplier |= uint32(b&0x7F) << shift
if b < 0x80 {
break
}
}
case 5:
if wireType != 0 {
return fmt.Errorf("proto: wrong wireType = %d for field EnableHeight", wireType)
}
m.EnableHeight = 0
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return ErrIntOverflowFeemarket
}
if iNdEx >= l {
return io.ErrUnexpectedEOF
}
b := dAtA[iNdEx]
iNdEx++
m.EnableHeight |= int64(b&0x7F) << shift
if b < 0x80 {
break
}
}
case 6:
if wireType != 2 {
return fmt.Errorf("proto: wrong wireType = %d for field BaseFee", wireType)
}
var stringLen uint64
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return ErrIntOverflowFeemarket
}
if iNdEx >= l {
return io.ErrUnexpectedEOF
}
b := dAtA[iNdEx]
iNdEx++
stringLen |= uint64(b&0x7F) << shift
if b < 0x80 {
break
}
}
intStringLen := int(stringLen)
if intStringLen < 0 {
return ErrInvalidLengthFeemarket
}
postIndex := iNdEx + intStringLen
if postIndex < 0 {
return ErrInvalidLengthFeemarket
}
if postIndex > l {
return io.ErrUnexpectedEOF
}
if err := m.BaseFee.Unmarshal(dAtA[iNdEx:postIndex]); err != nil {
return err
}
iNdEx = postIndex
default:
iNdEx = preIndex
skippy, err := skipFeemarket(dAtA[iNdEx:])
if err != nil {
return err
}
if (skippy < 0) || (iNdEx+skippy) < 0 {
return ErrInvalidLengthFeemarket
}
if (iNdEx + skippy) > l {
return io.ErrUnexpectedEOF
}
iNdEx += skippy
}
}
if iNdEx > l {
return io.ErrUnexpectedEOF
}
return nil
}
func skipFeemarket(dAtA []byte) (n int, err error) {
l := len(dAtA)
iNdEx := 0
depth := 0
for iNdEx < l {
var wire uint64
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return 0, ErrIntOverflowFeemarket
}
if iNdEx >= l {
return 0, io.ErrUnexpectedEOF
}
b := dAtA[iNdEx]
iNdEx++
wire |= (uint64(b) & 0x7F) << shift
if b < 0x80 {
break
}
}
wireType := int(wire & 0x7)
switch wireType {
case 0:
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return 0, ErrIntOverflowFeemarket
}
if iNdEx >= l {
return 0, io.ErrUnexpectedEOF
}
iNdEx++
if dAtA[iNdEx-1] < 0x80 {
break
}
}
case 1:
iNdEx += 8
case 2:
var length int
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return 0, ErrIntOverflowFeemarket
}
if iNdEx >= l {
return 0, io.ErrUnexpectedEOF
}
b := dAtA[iNdEx]
iNdEx++
length |= (int(b) & 0x7F) << shift
if b < 0x80 {
break
}
}
if length < 0 {
return 0, ErrInvalidLengthFeemarket
}
iNdEx += length
case 3:
depth++
case 4:
if depth == 0 {
return 0, ErrUnexpectedEndOfGroupFeemarket
}
depth--
case 5:
iNdEx += 4
default:
return 0, fmt.Errorf("proto: illegal wireType %d", wireType)
}
if iNdEx < 0 {
return 0, ErrInvalidLengthFeemarket
}
if depth == 0 {
return iNdEx, nil
}
}
return 0, io.ErrUnexpectedEOF
}
var (
ErrInvalidLengthFeemarket = fmt.Errorf("proto: negative length found during unmarshaling")
ErrIntOverflowFeemarket = fmt.Errorf("proto: integer overflow")
ErrUnexpectedEndOfGroupFeemarket = fmt.Errorf("proto: unexpected end of group")
)
+356
View File
@@ -0,0 +1,356 @@
// Code generated by protoc-gen-gogo. DO NOT EDIT.
// source: ethermint/feemarket/v1/genesis.proto
package types
import (
fmt "fmt"
_ "github.com/gogo/protobuf/gogoproto"
proto "github.com/gogo/protobuf/proto"
io "io"
math "math"
math_bits "math/bits"
)
// Reference imports to suppress errors if they are not otherwise used.
var _ = proto.Marshal
var _ = fmt.Errorf
var _ = math.Inf
// This is a compile-time assertion to ensure that this generated file
// is compatible with the proto package it is being compiled against.
// A compilation error at this line likely means your copy of the
// proto package needs to be updated.
const _ = proto.GoGoProtoPackageIsVersion3 // please upgrade the proto package
// GenesisState defines the feemarket module's genesis state.
type GenesisState struct {
// params defines all the paramaters of the module.
Params Params `protobuf:"bytes,1,opt,name=params,proto3" json:"params"`
// block gas is the amount of gas used on the last block before the upgrade.
// Zero by default.
BlockGas uint64 `protobuf:"varint,3,opt,name=block_gas,json=blockGas,proto3" json:"block_gas,omitempty"`
}
func (m *GenesisState) Reset() { *m = GenesisState{} }
func (m *GenesisState) String() string { return proto.CompactTextString(m) }
func (*GenesisState) ProtoMessage() {}
func (*GenesisState) Descriptor() ([]byte, []int) {
return fileDescriptor_6241c21661288629, []int{0}
}
func (m *GenesisState) XXX_Unmarshal(b []byte) error {
return m.Unmarshal(b)
}
func (m *GenesisState) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
if deterministic {
return xxx_messageInfo_GenesisState.Marshal(b, m, deterministic)
} else {
b = b[:cap(b)]
n, err := m.MarshalToSizedBuffer(b)
if err != nil {
return nil, err
}
return b[:n], nil
}
}
func (m *GenesisState) XXX_Merge(src proto.Message) {
xxx_messageInfo_GenesisState.Merge(m, src)
}
func (m *GenesisState) XXX_Size() int {
return m.Size()
}
func (m *GenesisState) XXX_DiscardUnknown() {
xxx_messageInfo_GenesisState.DiscardUnknown(m)
}
var xxx_messageInfo_GenesisState proto.InternalMessageInfo
func (m *GenesisState) GetParams() Params {
if m != nil {
return m.Params
}
return Params{}
}
func (m *GenesisState) GetBlockGas() uint64 {
if m != nil {
return m.BlockGas
}
return 0
}
var fileDescriptor_6241c21661288629 = []byte{
// 246 bytes of a gzipped FileDescriptorProto
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xe2, 0x52, 0x49, 0x2d, 0xc9, 0x48,
0x2d, 0xca, 0xcd, 0xcc, 0x2b, 0xd1, 0x4f, 0x4b, 0x4d, 0xcd, 0x4d, 0x2c, 0xca, 0x4e, 0x2d, 0xd1,
0x2f, 0x33, 0xd4, 0x4f, 0x4f, 0xcd, 0x4b, 0x2d, 0xce, 0x2c, 0xd6, 0x2b, 0x28, 0xca, 0x2f, 0xc9,
0x17, 0x12, 0x83, 0xab, 0xd2, 0x83, 0xab, 0xd2, 0x2b, 0x33, 0x94, 0x12, 0x49, 0xcf, 0x4f, 0xcf,
0x07, 0x2b, 0xd1, 0x07, 0xb1, 0x20, 0xaa, 0xa5, 0xd4, 0x70, 0x98, 0x89, 0xd0, 0x0a, 0x56, 0xa7,
0x54, 0xc9, 0xc5, 0xe3, 0x0e, 0xb1, 0x26, 0xb8, 0x24, 0xb1, 0x24, 0x55, 0xc8, 0x86, 0x8b, 0xad,
0x20, 0xb1, 0x28, 0x31, 0xb7, 0x58, 0x82, 0x51, 0x81, 0x51, 0x83, 0xdb, 0x48, 0x4e, 0x0f, 0xbb,
0xb5, 0x7a, 0x01, 0x60, 0x55, 0x4e, 0x2c, 0x27, 0xee, 0xc9, 0x33, 0x04, 0x41, 0xf5, 0x08, 0x49,
0x73, 0x71, 0x26, 0xe5, 0xe4, 0x27, 0x67, 0xc7, 0xa7, 0x27, 0x16, 0x4b, 0x30, 0x2b, 0x30, 0x6a,
0xb0, 0x04, 0x71, 0x80, 0x05, 0xdc, 0x13, 0x8b, 0xbd, 0x58, 0x38, 0x98, 0x04, 0x98, 0x83, 0x38,
0x92, 0x12, 0x8b, 0x53, 0xe3, 0xd3, 0x52, 0x53, 0x9d, 0x3c, 0x4e, 0x3c, 0x92, 0x63, 0xbc, 0xf0,
0x48, 0x8e, 0xf1, 0xc1, 0x23, 0x39, 0xc6, 0x09, 0x8f, 0xe5, 0x18, 0x2e, 0x3c, 0x96, 0x63, 0xb8,
0xf1, 0x58, 0x8e, 0x21, 0x4a, 0x2f, 0x3d, 0xb3, 0x24, 0xa3, 0x34, 0x49, 0x2f, 0x39, 0x3f, 0x57,
0xbf, 0x24, 0x23, 0xb1, 0xa8, 0x38, 0xb3, 0x58, 0x1f, 0xe1, 0x9f, 0x0a, 0x24, 0x1f, 0x95, 0x54,
0x16, 0xa4, 0x16, 0x27, 0xb1, 0x81, 0xfd, 0x62, 0x0c, 0x08, 0x00, 0x00, 0xff, 0xff, 0x3c, 0x4e,
0x2a, 0x68, 0x49, 0x01, 0x00, 0x00,
}
func (m *GenesisState) Marshal() (dAtA []byte, err error) {
size := m.Size()
dAtA = make([]byte, size)
n, err := m.MarshalToSizedBuffer(dAtA[:size])
if err != nil {
return nil, err
}
return dAtA[:n], nil
}
func (m *GenesisState) MarshalTo(dAtA []byte) (int, error) {
size := m.Size()
return m.MarshalToSizedBuffer(dAtA[:size])
}
func (m *GenesisState) MarshalToSizedBuffer(dAtA []byte) (int, error) {
i := len(dAtA)
_ = i
var l int
_ = l
if m.BlockGas != 0 {
i = encodeVarintGenesis(dAtA, i, uint64(m.BlockGas))
i--
dAtA[i] = 0x18
}
{
size, err := m.Params.MarshalToSizedBuffer(dAtA[:i])
if err != nil {
return 0, err
}
i -= size
i = encodeVarintGenesis(dAtA, i, uint64(size))
}
i--
dAtA[i] = 0xa
return len(dAtA) - i, nil
}
func encodeVarintGenesis(dAtA []byte, offset int, v uint64) int {
offset -= sovGenesis(v)
base := offset
for v >= 1<<7 {
dAtA[offset] = uint8(v&0x7f | 0x80)
v >>= 7
offset++
}
dAtA[offset] = uint8(v)
return base
}
func (m *GenesisState) Size() (n int) {
if m == nil {
return 0
}
var l int
_ = l
l = m.Params.Size()
n += 1 + l + sovGenesis(uint64(l))
if m.BlockGas != 0 {
n += 1 + sovGenesis(uint64(m.BlockGas))
}
return n
}
func sovGenesis(x uint64) (n int) {
return (math_bits.Len64(x|1) + 6) / 7
}
func sozGenesis(x uint64) (n int) {
return sovGenesis(uint64((x << 1) ^ uint64((int64(x) >> 63))))
}
func (m *GenesisState) Unmarshal(dAtA []byte) error {
l := len(dAtA)
iNdEx := 0
for iNdEx < l {
preIndex := iNdEx
var wire uint64
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return ErrIntOverflowGenesis
}
if iNdEx >= l {
return io.ErrUnexpectedEOF
}
b := dAtA[iNdEx]
iNdEx++
wire |= uint64(b&0x7F) << shift
if b < 0x80 {
break
}
}
fieldNum := int32(wire >> 3)
wireType := int(wire & 0x7)
if wireType == 4 {
return fmt.Errorf("proto: GenesisState: wiretype end group for non-group")
}
if fieldNum <= 0 {
return fmt.Errorf("proto: GenesisState: illegal tag %d (wire type %d)", fieldNum, wire)
}
switch fieldNum {
case 1:
if wireType != 2 {
return fmt.Errorf("proto: wrong wireType = %d for field Params", wireType)
}
var msglen int
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return ErrIntOverflowGenesis
}
if iNdEx >= l {
return io.ErrUnexpectedEOF
}
b := dAtA[iNdEx]
iNdEx++
msglen |= int(b&0x7F) << shift
if b < 0x80 {
break
}
}
if msglen < 0 {
return ErrInvalidLengthGenesis
}
postIndex := iNdEx + msglen
if postIndex < 0 {
return ErrInvalidLengthGenesis
}
if postIndex > l {
return io.ErrUnexpectedEOF
}
if err := m.Params.Unmarshal(dAtA[iNdEx:postIndex]); err != nil {
return err
}
iNdEx = postIndex
case 3:
if wireType != 0 {
return fmt.Errorf("proto: wrong wireType = %d for field BlockGas", wireType)
}
m.BlockGas = 0
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return ErrIntOverflowGenesis
}
if iNdEx >= l {
return io.ErrUnexpectedEOF
}
b := dAtA[iNdEx]
iNdEx++
m.BlockGas |= uint64(b&0x7F) << shift
if b < 0x80 {
break
}
}
default:
iNdEx = preIndex
skippy, err := skipGenesis(dAtA[iNdEx:])
if err != nil {
return err
}
if (skippy < 0) || (iNdEx+skippy) < 0 {
return ErrInvalidLengthGenesis
}
if (iNdEx + skippy) > l {
return io.ErrUnexpectedEOF
}
iNdEx += skippy
}
}
if iNdEx > l {
return io.ErrUnexpectedEOF
}
return nil
}
func skipGenesis(dAtA []byte) (n int, err error) {
l := len(dAtA)
iNdEx := 0
depth := 0
for iNdEx < l {
var wire uint64
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return 0, ErrIntOverflowGenesis
}
if iNdEx >= l {
return 0, io.ErrUnexpectedEOF
}
b := dAtA[iNdEx]
iNdEx++
wire |= (uint64(b) & 0x7F) << shift
if b < 0x80 {
break
}
}
wireType := int(wire & 0x7)
switch wireType {
case 0:
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return 0, ErrIntOverflowGenesis
}
if iNdEx >= l {
return 0, io.ErrUnexpectedEOF
}
iNdEx++
if dAtA[iNdEx-1] < 0x80 {
break
}
}
case 1:
iNdEx += 8
case 2:
var length int
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return 0, ErrIntOverflowGenesis
}
if iNdEx >= l {
return 0, io.ErrUnexpectedEOF
}
b := dAtA[iNdEx]
iNdEx++
length |= (int(b) & 0x7F) << shift
if b < 0x80 {
break
}
}
if length < 0 {
return 0, ErrInvalidLengthGenesis
}
iNdEx += length
case 3:
depth++
case 4:
if depth == 0 {
return 0, ErrUnexpectedEndOfGroupGenesis
}
depth--
case 5:
iNdEx += 4
default:
return 0, fmt.Errorf("proto: illegal wireType %d", wireType)
}
if iNdEx < 0 {
return 0, ErrInvalidLengthGenesis
}
if depth == 0 {
return iNdEx, nil
}
}
return 0, io.ErrUnexpectedEOF
}
var (
ErrInvalidLengthGenesis = fmt.Errorf("proto: negative length found during unmarshaling")
ErrIntOverflowGenesis = fmt.Errorf("proto: integer overflow")
ErrUnexpectedEndOfGroupGenesis = fmt.Errorf("proto: unexpected end of group")
)
+135
View File
@@ -0,0 +1,135 @@
package types
import (
"fmt"
sdkmath "cosmossdk.io/math"
paramtypes "github.com/cosmos/cosmos-sdk/x/params/types"
"github.com/ethereum/go-ethereum/params"
)
var _ paramtypes.ParamSet = &Params{}
// Parameter keys
var (
ParamStoreKeyNoBaseFee = []byte("NoBaseFee")
ParamStoreKeyBaseFeeChangeDenominator = []byte("BaseFeeChangeDenominator")
ParamStoreKeyElasticityMultiplier = []byte("ElasticityMultiplier")
ParamStoreKeyBaseFee = []byte("BaseFee")
ParamStoreKeyEnableHeight = []byte("EnableHeight")
)
// ParamKeyTable returns the parameter key table.
func ParamKeyTable() paramtypes.KeyTable {
return paramtypes.NewKeyTable().RegisterParamSet(&Params{})
}
// NewParams creates a new Params instance
func NewParams(noBaseFee bool, baseFeeChangeDenom, elasticityMultiplier uint32, baseFee uint64, enableHeight int64) Params {
return Params{
NoBaseFee: noBaseFee,
BaseFeeChangeDenominator: baseFeeChangeDenom,
ElasticityMultiplier: elasticityMultiplier,
BaseFee: sdkmath.NewIntFromUint64(baseFee),
EnableHeight: enableHeight,
}
}
// DefaultParams returns default evm parameters
func DefaultParams() Params {
return Params{
NoBaseFee: false,
BaseFeeChangeDenominator: params.BaseFeeChangeDenominator,
ElasticityMultiplier: params.ElasticityMultiplier,
BaseFee: sdkmath.NewIntFromUint64(params.InitialBaseFee),
EnableHeight: 0,
}
}
// ParamSetPairs returns the parameter set pairs.
func (p *Params) ParamSetPairs() paramtypes.ParamSetPairs {
return paramtypes.ParamSetPairs{
paramtypes.NewParamSetPair(ParamStoreKeyNoBaseFee, &p.NoBaseFee, validateBool),
paramtypes.NewParamSetPair(ParamStoreKeyBaseFeeChangeDenominator, &p.BaseFeeChangeDenominator, validateBaseFeeChangeDenominator),
paramtypes.NewParamSetPair(ParamStoreKeyElasticityMultiplier, &p.ElasticityMultiplier, validateElasticityMultiplier),
paramtypes.NewParamSetPair(ParamStoreKeyBaseFee, &p.BaseFee, validateBaseFee),
paramtypes.NewParamSetPair(ParamStoreKeyEnableHeight, &p.EnableHeight, validateEnableHeight),
}
}
// Validate performs basic validation on fee market parameters.
func (p Params) Validate() error {
if p.BaseFeeChangeDenominator == 0 {
return fmt.Errorf("base fee change denominator cannot be 0")
}
if p.BaseFee.IsNegative() {
return fmt.Errorf("initial base fee cannot be negative: %s", p.BaseFee)
}
if p.EnableHeight < 0 {
return fmt.Errorf("enable height cannot be negative: %d", p.EnableHeight)
}
return nil
}
func (p *Params) IsBaseFeeEnabled(height int64) bool {
return !p.NoBaseFee && height >= p.EnableHeight
}
func validateBool(i interface{}) error {
_, ok := i.(bool)
if !ok {
return fmt.Errorf("invalid parameter type: %T", i)
}
return nil
}
func validateBaseFeeChangeDenominator(i interface{}) error {
value, ok := i.(uint32)
if !ok {
return fmt.Errorf("invalid parameter type: %T", i)
}
if value == 0 {
return fmt.Errorf("base fee change denominator cannot be 0")
}
return nil
}
func validateElasticityMultiplier(i interface{}) error {
_, ok := i.(uint32)
if !ok {
return fmt.Errorf("invalid parameter type: %T", i)
}
return nil
}
func validateBaseFee(i interface{}) error {
value, ok := i.(sdkmath.Int)
if !ok {
return fmt.Errorf("invalid parameter type: %T", i)
}
if value.IsNegative() {
return fmt.Errorf("base fee cannot be negative")
}
return nil
}
func validateEnableHeight(i interface{}) error {
value, ok := i.(int64)
if !ok {
return fmt.Errorf("invalid parameter type: %T", i)
}
if value < 0 {
return fmt.Errorf("enable height cannot be negative: %d", value)
}
return nil
}
+43
View File
@@ -0,0 +1,43 @@
package v011
import (
sdk "github.com/cosmos/cosmos-sdk/types"
v010types "github.com/cerc-io/laconicd/x/feemarket/migrations/v010/types"
"github.com/cerc-io/laconicd/x/feemarket/types"
paramtypes "github.com/cosmos/cosmos-sdk/x/params/types"
)
// MigrateStore adds the MinGasPrice param with a value of 0
// and MinGasMultiplier to 0,5
func MigrateStore(ctx sdk.Context, paramstore *paramtypes.Subspace) error {
if !paramstore.HasKeyTable() {
ps := paramstore.WithKeyTable(types.ParamKeyTable())
paramstore = &ps
}
// add MinGasPrice
paramstore.Set(ctx, types.ParamStoreKeyMinGasPrice, types.DefaultMinGasPrice)
// add MinGasMultiplier
paramstore.Set(ctx, types.ParamStoreKeyMinGasMultiplier, types.DefaultMinGasMultiplier)
return nil
}
// MigrateJSON accepts exported v0.10 x/feemarket genesis state and migrates it to
// v0.11 x/feemarket genesis state. The migration includes:
// - add MinGasPrice param
// - add MinGasMultiplier param
func MigrateJSON(oldState v010types.GenesisState) types.GenesisState {
return types.GenesisState{
Params: types.Params{
NoBaseFee: oldState.Params.NoBaseFee,
BaseFeeChangeDenominator: oldState.Params.BaseFeeChangeDenominator,
ElasticityMultiplier: oldState.Params.ElasticityMultiplier,
EnableHeight: oldState.Params.EnableHeight,
BaseFee: oldState.Params.BaseFee,
MinGasPrice: types.DefaultMinGasPrice,
MinGasMultiplier: types.DefaultMinGasMultiplier,
},
BlockGas: oldState.BlockGas,
}
}
@@ -0,0 +1,88 @@
package v011_test
import (
"fmt"
"testing"
"github.com/stretchr/testify/require"
"github.com/cosmos/cosmos-sdk/testutil"
sdk "github.com/cosmos/cosmos-sdk/types"
paramtypes "github.com/cosmos/cosmos-sdk/x/params/types"
"github.com/cerc-io/laconicd/encoding"
"github.com/cerc-io/laconicd/app"
v010types "github.com/cerc-io/laconicd/x/feemarket/migrations/v010/types"
v011 "github.com/cerc-io/laconicd/x/feemarket/migrations/v011"
"github.com/cerc-io/laconicd/x/feemarket/types"
feemarkettypes "github.com/cerc-io/laconicd/x/feemarket/types"
)
func init() {
// modify defaults through global
types.DefaultMinGasPrice = sdk.NewDecWithPrec(25, 3)
}
func TestMigrateStore(t *testing.T) {
encCfg := encoding.MakeConfig(app.ModuleBasics)
feemarketKey := sdk.NewKVStoreKey(feemarkettypes.StoreKey)
tFeeMarketKey := sdk.NewTransientStoreKey(fmt.Sprintf("%s_test", feemarkettypes.StoreKey))
ctx := testutil.DefaultContext(feemarketKey, tFeeMarketKey)
paramstore := paramtypes.NewSubspace(
encCfg.Codec, encCfg.Amino, feemarketKey, tFeeMarketKey, "feemarket",
)
paramstore = paramstore.WithKeyTable(feemarkettypes.ParamKeyTable())
require.True(t, paramstore.HasKeyTable())
// check no MinGasPrice param
require.False(t, paramstore.Has(ctx, feemarkettypes.ParamStoreKeyMinGasPrice))
require.False(t, paramstore.Has(ctx, feemarkettypes.ParamStoreKeyMinGasMultiplier))
// Run migrations
err := v011.MigrateStore(ctx, &paramstore)
require.NoError(t, err)
// Make sure the params are set
require.True(t, paramstore.Has(ctx, feemarkettypes.ParamStoreKeyMinGasPrice))
require.True(t, paramstore.Has(ctx, feemarkettypes.ParamStoreKeyMinGasMultiplier))
var (
minGasPrice sdk.Dec
minGasMultiplier sdk.Dec
)
// Make sure the new params are set
require.NotPanics(t, func() {
paramstore.Get(ctx, feemarkettypes.ParamStoreKeyMinGasPrice, &minGasPrice)
paramstore.Get(ctx, feemarkettypes.ParamStoreKeyMinGasMultiplier, &minGasMultiplier)
})
// check the params are updated
require.Equal(t, types.DefaultMinGasPrice.String(), minGasPrice.String())
require.False(t, minGasPrice.IsZero())
require.Equal(t, types.DefaultMinGasMultiplier.String(), minGasMultiplier.String())
}
func TestMigrateJSON(t *testing.T) {
rawJson := `{
"block_gas": "0",
"params": {
"base_fee_change_denominator": 8,
"elasticity_multiplier": 2,
"enable_height": "0",
"base_fee": "1000000000",
"no_base_fee": false
}
}`
encCfg := encoding.MakeConfig(app.ModuleBasics)
var genState v010types.GenesisState
err := encCfg.Codec.UnmarshalJSON([]byte(rawJson), &genState)
require.NoError(t, err)
migratedGenState := v011.MigrateJSON(genState)
require.Equal(t, types.DefaultMinGasPrice, migratedGenState.Params.MinGasPrice)
require.Equal(t, types.DefaultMinGasMultiplier, migratedGenState.Params.MinGasMultiplier)
}
@@ -106,14 +106,6 @@ func (m *Params) GetEnableHeight() int64 {
return 0
}
func init() {
proto.RegisterType((*Params)(nil), "ethermint.feemarket.v1.Params")
}
func init() {
proto.RegisterFile("ethermint/feemarket/v1/feemarket.proto", fileDescriptor_4feb8b20cf98e6e1)
}
var fileDescriptor_4feb8b20cf98e6e1 = []byte{
// 286 bytes of a gzipped FileDescriptorProto
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x4c, 0x90, 0xc1, 0x4a, 0x03, 0x31,
@@ -83,14 +83,6 @@ func (m *GenesisState) GetBlockGas() uint64 {
return 0
}
func init() {
proto.RegisterType((*GenesisState)(nil), "ethermint.feemarket.v1.GenesisState")
}
func init() {
proto.RegisterFile("ethermint/feemarket/v1/genesis.proto", fileDescriptor_6241c21661288629)
}
var fileDescriptor_6241c21661288629 = []byte{
// 286 bytes of a gzipped FileDescriptorProto
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x74, 0x90, 0x31, 0x4b, 0xc3, 0x40,
+8 -3
View File
@@ -44,7 +44,7 @@ func (AppModuleBasic) RegisterLegacyAminoCodec(_ *codec.LegacyAmino) {
// ConsensusVersion returns the consensus state-breaking version for the module.
func (AppModuleBasic) ConsensusVersion() uint64 {
return 2
return 3
}
// DefaultGenesis returns default genesis state as raw bytes for the fee market
@@ -112,8 +112,8 @@ func (AppModule) Name() string {
// as the fee market module doesn't expose invariants.
func (am AppModule) RegisterInvariants(ir sdk.InvariantRegistry) {}
// RegisterQueryService registers a GRPC query service to respond to the
// module-specific GRPC queries.
// RegisterServices registers the GRPC query service and migrator service to respond to the
// module-specific GRPC queries and handle the upgrade store migration for the module.
func (am AppModule) RegisterServices(cfg module.Configurator) {
types.RegisterQueryServer(cfg.QueryServer(), am.keeper)
@@ -122,6 +122,11 @@ func (am AppModule) RegisterServices(cfg module.Configurator) {
if err != nil {
panic(err)
}
err = cfg.RegisterMigration(types.ModuleName, 2, m.Migrate2to3)
if err != nil {
panic(err)
}
}
// Route returns the message routing key for the fee market module.
+9 -1
View File
@@ -4,6 +4,7 @@ import (
"encoding/json"
"fmt"
sdk "github.com/cosmos/cosmos-sdk/types"
"github.com/cosmos/cosmos-sdk/types/module"
"github.com/cerc-io/laconicd/x/feemarket/types"
@@ -11,7 +12,14 @@ import (
// RandomizedGenState generates a random GenesisState for nft
func RandomizedGenState(simState *module.SimulationState) {
params := types.NewParams(simState.Rand.Uint32()%2 == 0, simState.Rand.Uint32(), simState.Rand.Uint32(), simState.Rand.Uint64(), simState.Rand.Int63())
params := types.NewParams(simState.Rand.Uint32()%2 == 0,
simState.Rand.Uint32(),
simState.Rand.Uint32(),
simState.Rand.Uint64(),
simState.Rand.Int63(),
sdk.ZeroDec(),
types.DefaultMinGasMultiplier)
blockGas := simState.Rand.Uint64()
feemarketGenesis := types.NewGenesisState(params, blockGas)
+54 -14
View File
@@ -4,32 +4,72 @@ order: 1
# Concepts
## Base fee
## EIP-1559: Fee Market
The base fee is a global base fee defined at the consensus level. It is adjusted for each block based on the total gas used in the previous block and gas target (block gas limit divided by elasticity multiplier)
[EIP-1559](https://github.com/ethereum/EIPs/blob/master/EIPS/eip-1559.md) describes a pricing mechanism that was proposed on Ethereum to improve to calculation of transaction fees. It includes a fixed-per-block network fee that is burned and dynamically expands/contracts block sizes to deal with peaks of network congestion.
- it increases when blocks are above the gas target
- it decreases when blocks are below the gas target
Before EIP-1559 the transaction fee is calculated with
Unlike the Cosmos SDK local `minimal-gas-prices`, this value is stored as a module parameter which provides a reliable value for validators to agree upon.
```
fee = gasPrice * gasLimit
```
## Tip
, where `gasPrice` is the price per gas and `gasLimit` describes the amount of gas required to perform the transaction. The more complex operations a transaction requires, the higher the gasLimit (See [Executing EVM bytecode](https://docs.evmos.org/modules/evm/01_concepts.html#executing-evm-bytecode)). To submit a transaction, the signer needs to specify the `gasPrice`.
In EIP-1559, the `tip` is a value that can be added to the `baseFee` in order to incentive transaction prioritization.
With EIP-1559 enabled, the transaction fee is calculated with
The transaction fee in Ethereum is calculated using the following the formula :
```
fee = (baseFee + priorityTip) * gasLimit
```
`transaction fee = (baseFee + tip) * gas units (limit)`
, where `baseFee` is the fixed-per-block network fee per gas and `priorityTip` is an additional fee per gas that can be set optionally. Note, that both the base fee and the priority tip are a gas prices. To submit a transaction with EIP-1559, the signer needs to specify the `gasFeeCap` a maximum fee per gas they are willing to pay total and optionally the `priorityTip` , which covers both the priority fee and the block's network fee per gas (aka: base fee).
In Cosmos SDK there is no notion of prioritization, thus the tip for an EIP-1559 transaction in Ethermint should be zero (`MaxPriorityFeePerGas` JSON-RPC endpoint returns `0`)
::: tip
The Cosmos SDK uses a different terminology for `gas` than Ethereum. What is called `gasLimit` on Ethereum is called `gasWanted` on Cosmos. You might encounter both terminologies on Evmos since it builds Ethereum on top of the SDK, e.g. when using different wallets like Keplr for Cosmos and Metamask for Ethereum.
:::
## Base Fee
The base fee per gas (aka base fee) is a global gas price defined at the consensus level. It is stored as a module parameter and is adjusted at the end of each block based on the total gas used in the previous block and gas target (`block gas limit / elasticity multiplier`):
## EIP-1559
- it increases when blocks are above the gas target,
- it decreases when blocks are below the gas target.
A transaction pricing mechanism introduced in Ethereum that includes fixed-per-block network fee that is burned and dynamically expands/contracts block sizes to deal with transient congestion.
Instead of burning the base fee (as implemented on Ethereum), the `feemarket` module allocates the base fee for regular [Cosmos SDK fee distribution](https://docs.evmos.org/modules/distribution/).
Transactions specify a maximum fee per gas they are willing to pay total (aka: max fee), which covers both the priority fee and the block's network fee per gas (aka: base fee)
## Priority Tip
Reference: [EIP1559](https://eips.ethereum.org/EIPS/eip-1559)
In EIP-1559, the `max_priority_fee_per_gas`, often referred to as `tip`, is an additional gas price that can be added to the `baseFee` in order to incentive transaction prioritization. The higher the tip, the more likely the transaction is included in the block.
Until the Cosmos SDK version v0.46, however, there is no notion of transaction prioritization. Thus the tip for an EIP-1559 transaction on Ethermint should be zero (`MaxPriorityFeePerGas` JSON-RPC endpoint returns `0`). Have a look at [ADR 067](https://github.com/tendermint/tendermint/blob/master/docs/architecture/adr-067-mempool-refactor.md) to read about future plans on transaction prioritization in the Cosmos SDK.
## Effective Gas price
For EIP-1559 transactions (dynamic fee transactions) the effective gas price descibes the maximum gas price that a transaction is willing to provide. It is derived from the transaction arguments and the base fee parameter. Depending on which one is smaller, the effective gas price is either the `baseFee + tip` or the `gasFeeCap`
```
min(baseFee + gasTipCap, gasFeeCap)
```
## Local vs. Global Minimum Gas Prices
Minimum gas prices are used to discard spam transactions in the network, by raising the cost of transactions to the point that it is not economically viable for the spammer. This is achieved by defining a minimum gas price for accepting txs in the mempool for both Cosmos and EVM transactions. A transaction is discarded from the mempool if it doesn't provide at least one of the two types of min gas prices:
Minimum gas prices are used to discard spam transactions in the network, by raising the cost of transactions to the point that it is not economically viable for the spammer. This is achieved by defining a minimum gas price for accepting txs in the mempool for both Cosmos and EVM transactions. A transaction is discarded from the mempool if it doesn't provide at least one of the two types of min gas prices:
1. the local min gas prices that validators can set on their node config and
2. the global min gas price, which is set as a parameter in the `feemarket` module, which can be changed through governance.
The lower bound for a transaction gas price is determined by comparing of gas price bounds according to three cases:
1. If the effective gas price (`effective gas price = base fee + priority tip`) or the local minimum gas price is lower than the global `MinGasPrice` (`min-gas-price (local) < MinGasPrice (global) OR EffectiveGasPrice < MinGasPrice`), then `MinGasPrice` is used as a lower bound.
2. If transactions are rejected due to having a gas price lower than `MinGasPrice`, users need to resend the transactions with a gas price higher or equal to `MinGasPrice`.
3. If the effective gas price or the local `minimum-gas-price` is higher than the global `MinGasPrice`, then the larger value of the two is used as a lower bound. In the case of EIP-1559, users must increase the priority fee for their transactions to be valid.
The comparison of transaction gas price and the lower bound is implemented through AnteHandler decorators. For EVM transactions, this is done in the `EthMempoolFeeDecorator` and `EthMinGasPriceDecorator` `AnteHandler` and for Cosmos transactions in `NewMempoolFeeDecorator` and `MinGasPriceDecorator` `AnteHandler`.
::: tip
If the base fee decreases to a value below the global `MinGasPrice`, it is set to the `MinGasPrice`. This is implemented, so that the base fee can't drop to gas prices that wouldn't allow transactions to be accepted in the mempool, because of a higher `MinGasPrice`.
:::
-1
View File
@@ -8,7 +8,6 @@ The x/feemarket module keeps in the state variable needed to the fee calculation
Only BlockGasUsed in previous block needs to be tracked in state for the next base fee calculation.
| | Description | Key | Value | Store |
| ----------- | ------------------------------ | ---------------| ------------------- | --------- |
| BlockGasUsed | gas used in the block | `[]byte{1}` | `[]byte{gas_used}` | KV |
+3 -3
View File
@@ -4,7 +4,7 @@ order: 3
# Begin block
The base fee is calculated at the beginning of each block.
The base fee is calculated at the beginning of each block.
## Base Fee
@@ -15,6 +15,7 @@ We introduce two parameters : `NoBaseFee`and `EnableHeight`
`NoBaseFee` controls the feemarket base fee value. If set to true, no calculation is done and the base fee returned by the keeper is zero.
`EnableHeight` controls the height we start the calculation.
- If `NoBaseFee = false` and `height < EnableHeight`, the base fee value will be equal to `base_fee` defined in the genesis and the `BeginBlock` will return without further computation.
- If `NoBaseFee = false` and `height >= EnableHeight`, the base fee is dynamically calculated upon each block at `BeginBlock`.
@@ -28,7 +29,6 @@ To enable EIP1559 with the EVM, the following parameters should be set :
- EnableHeight should be set to a positive integer >= upgrade height. It defines at which height the chain starts the base fee adjustment
- LondonBlock evm's param should be set to a positive integer >= upgrade height. It defines at which height the chain start to accept EIP1559 transactions
### Calculation
The base fee is initialized at `EnableHeight` to the `InitialBaseFee` value defined in the genesis file.
@@ -51,4 +51,4 @@ else:
base_fee_delta = parent_base_fee * gas_used_delta / parent_gas_target / BASE_FEE_MAX_CHANGE_DENOMINATOR
base_fee = parent_base_fee - base_fee_delta
```
```
+2 -2
View File
@@ -4,10 +4,10 @@ order: 4
# End block
The block_gas_used value is updated at the end of each block.
The block_gas_used value is updated at the end of each block.
## Block Gas Used
The total gas used by current block is stored in the KVStore at `EndBlock`.
It is initialized to `block_gas` defined in the genesis.
It is initialized to `block_gas` defined in the genesis.
+1 -1
View File
@@ -12,4 +12,4 @@ type Keeper interface {
GetBaseFee(ctx sdk.Context) *big.Int
}
```
```
+2 -1
View File
@@ -11,4 +11,5 @@ The `x/feemarket` module contains the following parameters:
| BaseFeeChangeDenominator | uint32 | 8 | bounds the amount the base fee that can change between blocks |
| ElasticityMultiplier | uint32 | 2 | bounds the threshold which the base fee will increase or decrease depending on the total gas used in the previous block|
| BaseFee | uint32 | 1000000000 | base fee for EIP-1559 blocks |
| EnableHeight | uint32 | 0 | height which enable fee adjustment |
| EnableHeight | uint32 | 0 | height which enable fee adjustment |
| MinGasPrice | sdk.Dec | 0 | global minimum gas price that needs to be paid to include a transaction in a block |
-1
View File
@@ -77,7 +77,6 @@ subspace: feemarket
value: "2"
```
## gRPC
### Queries
+37
View File
@@ -0,0 +1,37 @@
<!--
order: 5
-->
# AnteHandlers
The `x/feemarket` module provides `AnteDecorator`s that are recursively chained together into a single [`Antehandler`](https://github.com/cosmos/cosmos-sdk/blob/v0.43.0-alpha1/docs/architecture/adr-010-modular-antehandler.md). These decorators perform basic validity checks on an Ethereum or Cosmos SDK transaction, such that it could be thrown out of the transaction Mempool.
Note that the `AnteHandler` is run for every transaction and called on both `CheckTx` and `DeliverTx`.
## Decorators
### `MinGasPriceDecorator`
Rejects Cosmos SDK transactions with transaction fees lower than `MinGasPrice * GasLimit`.
### `EthMinGasPriceDecorator`
Rejects EVM transactions with transactions fees lower than `MinGasPrice * GasLimit`.
- For `LegacyTx` and `AccessListTx`, the `GasPrice * GasLimit` is used.
- For EIP-1559 (*aka.* `DynamicFeeTx`), the `EffectivePrice * GasLimit` is used.
::: tip
**Note**: For dynamic transactions, if the `feemarket` formula results in a `BaseFee` that lowers `EffectivePrice < MinGasPrices`, the users must increase the `GasTipCap` (priority fee) until `EffectivePrice > MinGasPrices`. Transactions with `MinGasPrices * GasLimit < transaction fee < EffectiveFee` are rejected by the `feemarket` `AnteHandle`.
:::
### `EthGasConsumeDecorator`
Calculates the effective fees to deduct and the tx priority according to EIP-1559 spec, then deducts the fees and sets the tx priority in the response.
```
effectivePrice = min(baseFee + tipFeeCap, gasFeeCap)
effectiveTipFee = effectivePrice - baseFee
priority = effectiveTipFee / DefaultPriorityReduction
```
When there are multiple messages in the transaction, choose the lowest priority in them.
@@ -4,4 +4,3 @@ order: 9 -->
# Future Improvements
- The feemarket module has been designed mainly to support EIP-1559 on EVM-based chain on cosmos, supporting non-EVM chain could be done as a future improvements.
+3 -5
View File
@@ -13,13 +13,11 @@ This document specifies the feemarket module which allows to define a global tra
This module has been designed to support EIP1559 in cosmos-sdk.
The `MempoolFeeDecorator` in `x/auth` module needs to be overrided to check the `baseFee` along with the `minimal-gas-prices` allowing to implement a global fee mechanism which vary depending on the network activity.
The `MempoolFeeDecorator` in `x/auth` module needs to be overrided to check the `baseFee` along with the `minimal-gas-prices` allowing to implement a global fee mechanism which vary depending on the network activity.
For more reference to EIP1559:
https://github.com/ethereum/EIPs/blob/master/EIPS/eip-1559.md
<https://github.com/ethereum/EIPs/blob/master/EIPS/eip-1559.md>
## Contents
@@ -31,4 +29,4 @@ https://github.com/ethereum/EIPs/blob/master/EIPS/eip-1559.md
6. **[Events](06_events.md)**
7. **[Params](07_params.md)**
8. **[Client](08_client.md)**
9. **[Future Improvements](09_future_improvements.md)**
9. **[Future Improvements](09_future_improvements.md)**
+123 -23
View File
@@ -38,6 +38,11 @@ type Params struct {
EnableHeight int64 `protobuf:"varint,5,opt,name=enable_height,json=enableHeight,proto3" json:"enable_height,omitempty"`
// base fee for EIP-1559 blocks.
BaseFee github_com_cosmos_cosmos_sdk_types.Int `protobuf:"bytes,6,opt,name=base_fee,json=baseFee,proto3,customtype=github.com/cosmos/cosmos-sdk/types.Int" json:"base_fee"`
// min_gas_price defines the minimum gas price value for cosmos and eth transactions
MinGasPrice github_com_cosmos_cosmos_sdk_types.Dec `protobuf:"bytes,7,opt,name=min_gas_price,json=minGasPrice,proto3,customtype=github.com/cosmos/cosmos-sdk/types.Dec" json:"min_gas_price"`
// min gas denominator bounds the minimum gasUsed to be charged
// to senders based on GasLimit
MinGasMultiplier github_com_cosmos_cosmos_sdk_types.Dec `protobuf:"bytes,8,opt,name=min_gas_multiplier,json=minGasMultiplier,proto3,customtype=github.com/cosmos/cosmos-sdk/types.Dec" json:"min_gas_multiplier"`
}
func (m *Params) Reset() { *m = Params{} }
@@ -110,29 +115,32 @@ func init() {
}
var fileDescriptor_4feb8b20cf98e6e1 = []byte{
// 345 bytes of a gzipped FileDescriptorProto
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x4c, 0x91, 0xcf, 0x4a, 0xc3, 0x40,
0x10, 0x87, 0xb3, 0xfd, 0x67, 0x1b, 0x2d, 0x94, 0x50, 0x25, 0x28, 0xa4, 0x41, 0xa1, 0xe4, 0xd2,
0x84, 0xd2, 0xb3, 0x97, 0x2a, 0x6a, 0x05, 0x41, 0x72, 0xf4, 0x12, 0x36, 0xe9, 0x34, 0x59, 0x9a,
0xdd, 0x2d, 0xbb, 0xdb, 0x62, 0xdf, 0xc2, 0x87, 0xf0, 0x61, 0x7a, 0xec, 0x51, 0x3c, 0x14, 0x69,
0x5f, 0x44, 0x4c, 0x6b, 0xd2, 0xd3, 0xee, 0xce, 0xf7, 0x2d, 0x33, 0xfc, 0x46, 0xef, 0x82, 0x4a,
0x40, 0x50, 0xc2, 0x94, 0x37, 0x01, 0xa0, 0x58, 0x4c, 0x41, 0x79, 0x8b, 0x7e, 0xf1, 0x70, 0x67,
0x82, 0x2b, 0x6e, 0x5c, 0xe4, 0x9e, 0x5b, 0xa0, 0x45, 0xff, 0xb2, 0x1d, 0xf3, 0x98, 0x67, 0x8a,
0xf7, 0x77, 0xdb, 0xdb, 0xd7, 0x9f, 0x25, 0xbd, 0xf6, 0x8a, 0x05, 0xa6, 0xd2, 0xb0, 0xf4, 0x53,
0xc6, 0x83, 0x10, 0x4b, 0x08, 0x26, 0x00, 0x26, 0xb2, 0x91, 0x53, 0xf7, 0x1b, 0x8c, 0x0f, 0xb1,
0x84, 0x07, 0x00, 0xe3, 0x56, 0xbf, 0xfa, 0x87, 0x41, 0x94, 0x60, 0x16, 0x43, 0x30, 0x06, 0xc6,
0x29, 0x61, 0x58, 0x71, 0x61, 0x96, 0x6c, 0xe4, 0x34, 0x7d, 0x33, 0xdc, 0xdb, 0x77, 0x99, 0x70,
0x5f, 0x70, 0x63, 0xa0, 0x9f, 0x43, 0x8a, 0xa5, 0x22, 0x11, 0x51, 0xcb, 0x80, 0xce, 0x53, 0x45,
0x66, 0x29, 0x01, 0x61, 0x96, 0xb3, 0x8f, 0xed, 0x02, 0xbe, 0xe4, 0xcc, 0xb8, 0xd1, 0x9b, 0xc0,
0x70, 0x98, 0x42, 0x90, 0x00, 0x89, 0x13, 0x65, 0x56, 0x6d, 0xe4, 0x94, 0xfd, 0xb3, 0x7d, 0xf1,
0x29, 0xab, 0x19, 0x23, 0xbd, 0x9e, 0x4f, 0x5d, 0xb3, 0x91, 0xd3, 0x18, 0xba, 0xab, 0x4d, 0x47,
0xfb, 0xde, 0x74, 0xba, 0x31, 0x51, 0xc9, 0x3c, 0x74, 0x23, 0x4e, 0xbd, 0x88, 0x4b, 0xca, 0xe5,
0xe1, 0xe8, 0xc9, 0xf1, 0xd4, 0x53, 0xcb, 0x19, 0x48, 0x77, 0xc4, 0x94, 0x7f, 0x72, 0x98, 0xfa,
0xb9, 0x52, 0xaf, 0xb4, 0xaa, 0x7e, 0x8b, 0x30, 0xa2, 0x08, 0x4e, 0xf3, 0x30, 0x86, 0x8f, 0xab,
0xad, 0x85, 0xd6, 0x5b, 0x0b, 0xfd, 0x6c, 0x2d, 0xf4, 0xb1, 0xb3, 0xb4, 0xf5, 0xce, 0xd2, 0xbe,
0x76, 0x96, 0xf6, 0xd6, 0x3b, 0x6e, 0x01, 0x22, 0xea, 0x11, 0xee, 0xa5, 0x38, 0xe2, 0x8c, 0x44,
0x63, 0xef, 0xfd, 0x68, 0x55, 0x59, 0xb7, 0xb0, 0x96, 0xc5, 0x3e, 0xf8, 0x0d, 0x00, 0x00, 0xff,
0xff, 0xe0, 0x3f, 0x15, 0x6e, 0xce, 0x01, 0x00, 0x00,
// 388 bytes of a gzipped FileDescriptorProto
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x9c, 0x52, 0xc1, 0x8a, 0xdb, 0x30,
0x14, 0xb4, 0x9a, 0xdd, 0xac, 0x57, 0xdb, 0x40, 0x10, 0xdb, 0x62, 0x5a, 0xf0, 0x9a, 0x16, 0x16,
0x1f, 0x5a, 0x9b, 0x65, 0xcf, 0xbd, 0xa4, 0x21, 0x6d, 0x0a, 0x85, 0xe0, 0x63, 0x29, 0x08, 0xd9,
0x79, 0xb1, 0x45, 0x2c, 0xc9, 0x58, 0x4a, 0x68, 0xfe, 0xa2, 0x9f, 0x95, 0x63, 0x4e, 0xa5, 0xf4,
0x10, 0x4a, 0xf2, 0x23, 0x25, 0x76, 0x62, 0xe7, 0xda, 0x3d, 0x49, 0x7a, 0x33, 0x9a, 0x79, 0xd2,
0x1b, 0x7c, 0x0f, 0x26, 0x83, 0x52, 0x70, 0x69, 0xc2, 0x19, 0x80, 0x60, 0xe5, 0x1c, 0x4c, 0xb8,
0x7c, 0x68, 0x0f, 0x41, 0x51, 0x2a, 0xa3, 0xc8, 0xcb, 0x86, 0x17, 0xb4, 0xd0, 0xf2, 0xe1, 0xd5,
0x6d, 0xaa, 0x52, 0x55, 0x51, 0xc2, 0xc3, 0xae, 0x66, 0xbf, 0xf9, 0xd5, 0xc1, 0xdd, 0x09, 0x2b,
0x99, 0xd0, 0xc4, 0xc5, 0x37, 0x52, 0xd1, 0x98, 0x69, 0xa0, 0x33, 0x00, 0x07, 0x79, 0xc8, 0xb7,
0xa3, 0x6b, 0xa9, 0x06, 0x4c, 0xc3, 0x08, 0x80, 0x7c, 0xc0, 0xaf, 0x4f, 0x20, 0x4d, 0x32, 0x26,
0x53, 0xa0, 0x53, 0x90, 0x4a, 0x70, 0xc9, 0x8c, 0x2a, 0x9d, 0x67, 0x1e, 0xf2, 0x7b, 0x91, 0x13,
0xd7, 0xec, 0x8f, 0x15, 0x61, 0xd8, 0xe2, 0xe4, 0x11, 0xbf, 0x80, 0x9c, 0x69, 0xc3, 0x13, 0x6e,
0x56, 0x54, 0x2c, 0x72, 0xc3, 0x8b, 0x9c, 0x43, 0xe9, 0x74, 0xaa, 0x8b, 0xb7, 0x2d, 0xf8, 0xb5,
0xc1, 0xc8, 0x5b, 0xdc, 0x03, 0xc9, 0xe2, 0x1c, 0x68, 0x06, 0x3c, 0xcd, 0x8c, 0x73, 0xe9, 0x21,
0xbf, 0x13, 0x3d, 0xaf, 0x8b, 0x9f, 0xab, 0x1a, 0x19, 0x63, 0xbb, 0xe9, 0xba, 0xeb, 0x21, 0xff,
0x7a, 0x10, 0xac, 0xb7, 0x77, 0xd6, 0x9f, 0xed, 0xdd, 0x7d, 0xca, 0x4d, 0xb6, 0x88, 0x83, 0x44,
0x89, 0x30, 0x51, 0x5a, 0x28, 0x7d, 0x5c, 0xde, 0xeb, 0xe9, 0x3c, 0x34, 0xab, 0x02, 0x74, 0x30,
0x96, 0x26, 0xba, 0x3a, 0x76, 0x4d, 0x22, 0xdc, 0x13, 0x5c, 0xd2, 0x94, 0x69, 0x5a, 0x94, 0x3c,
0x01, 0xe7, 0xea, 0xbf, 0xf5, 0x86, 0x90, 0x44, 0x37, 0x82, 0xcb, 0x4f, 0x4c, 0x4f, 0x0e, 0x12,
0xe4, 0x3b, 0x26, 0x27, 0xcd, 0xb3, 0x57, 0xdb, 0x4f, 0x12, 0xee, 0xd7, 0xc2, 0xed, 0x0f, 0x7d,
0xb9, 0xb0, 0x2f, 0xfa, 0x97, 0x51, 0x9f, 0x4b, 0x6e, 0x38, 0xcb, 0x9b, 0xf1, 0x0d, 0x46, 0xeb,
0x9d, 0x8b, 0x36, 0x3b, 0x17, 0xfd, 0xdd, 0xb9, 0xe8, 0xe7, 0xde, 0xb5, 0x36, 0x7b, 0xd7, 0xfa,
0xbd, 0x77, 0xad, 0x6f, 0xef, 0xce, 0xbc, 0x60, 0x79, 0xb0, 0x6a, 0x93, 0xf5, 0xe3, 0x2c, 0x5b,
0x95, 0x6b, 0xdc, 0xad, 0x72, 0xf2, 0xf8, 0x2f, 0x00, 0x00, 0xff, 0xff, 0xa5, 0xce, 0xeb, 0x97,
0x7f, 0x02, 0x00, 0x00,
}
func (m *Params) Marshal() (dAtA []byte, err error) {
@@ -155,6 +163,26 @@ func (m *Params) MarshalToSizedBuffer(dAtA []byte) (int, error) {
_ = i
var l int
_ = l
{
size := m.MinGasMultiplier.Size()
i -= size
if _, err := m.MinGasMultiplier.MarshalTo(dAtA[i:]); err != nil {
return 0, err
}
i = encodeVarintFeemarket(dAtA, i, uint64(size))
}
i--
dAtA[i] = 0x42
{
size := m.MinGasPrice.Size()
i -= size
if _, err := m.MinGasPrice.MarshalTo(dAtA[i:]); err != nil {
return 0, err
}
i = encodeVarintFeemarket(dAtA, i, uint64(size))
}
i--
dAtA[i] = 0x3a
{
size := m.BaseFee.Size()
i -= size
@@ -224,6 +252,10 @@ func (m *Params) Size() (n int) {
}
l = m.BaseFee.Size()
n += 1 + l + sovFeemarket(uint64(l))
l = m.MinGasPrice.Size()
n += 1 + l + sovFeemarket(uint64(l))
l = m.MinGasMultiplier.Size()
n += 1 + l + sovFeemarket(uint64(l))
return n
}
@@ -373,6 +405,74 @@ func (m *Params) Unmarshal(dAtA []byte) error {
return err
}
iNdEx = postIndex
case 7:
if wireType != 2 {
return fmt.Errorf("proto: wrong wireType = %d for field MinGasPrice", wireType)
}
var stringLen uint64
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return ErrIntOverflowFeemarket
}
if iNdEx >= l {
return io.ErrUnexpectedEOF
}
b := dAtA[iNdEx]
iNdEx++
stringLen |= uint64(b&0x7F) << shift
if b < 0x80 {
break
}
}
intStringLen := int(stringLen)
if intStringLen < 0 {
return ErrInvalidLengthFeemarket
}
postIndex := iNdEx + intStringLen
if postIndex < 0 {
return ErrInvalidLengthFeemarket
}
if postIndex > l {
return io.ErrUnexpectedEOF
}
if err := m.MinGasPrice.Unmarshal(dAtA[iNdEx:postIndex]); err != nil {
return err
}
iNdEx = postIndex
case 8:
if wireType != 2 {
return fmt.Errorf("proto: wrong wireType = %d for field MinGasMultiplier", wireType)
}
var stringLen uint64
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return ErrIntOverflowFeemarket
}
if iNdEx >= l {
return io.ErrUnexpectedEOF
}
b := dAtA[iNdEx]
iNdEx++
stringLen |= uint64(b&0x7F) << shift
if b < 0x80 {
break
}
}
intStringLen := int(stringLen)
if intStringLen < 0 {
return ErrInvalidLengthFeemarket
}
postIndex := iNdEx + intStringLen
if postIndex < 0 {
return ErrInvalidLengthFeemarket
}
if postIndex > l {
return io.ErrUnexpectedEOF
}
if err := m.MinGasMultiplier.Unmarshal(dAtA[iNdEx:postIndex]); err != nil {
return err
}
iNdEx = postIndex
default:
iNdEx = preIndex
skippy, err := skipFeemarket(dAtA[iNdEx:])
+7 -7
View File
@@ -27,7 +27,7 @@ const _ = proto.GoGoProtoPackageIsVersion3 // please upgrade the proto package
type GenesisState struct {
// params defines all the paramaters of the module.
Params Params `protobuf:"bytes,1,opt,name=params,proto3" json:"params"`
// block gas is the amount of gas used on the last block before the upgrade.
// block gas is the amount of gas wanted on the last block before the upgrade.
// Zero by default.
BlockGas uint64 `protobuf:"varint,3,opt,name=block_gas,json=blockGas,proto3" json:"block_gas,omitempty"`
}
@@ -88,7 +88,7 @@ func init() {
}
var fileDescriptor_6241c21661288629 = []byte{
// 253 bytes of a gzipped FileDescriptorProto
// 244 bytes of a gzipped FileDescriptorProto
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xe2, 0x52, 0x49, 0x2d, 0xc9, 0x48,
0x2d, 0xca, 0xcd, 0xcc, 0x2b, 0xd1, 0x4f, 0x4b, 0x4d, 0xcd, 0x4d, 0x2c, 0xca, 0x4e, 0x2d, 0xd1,
0x2f, 0x33, 0xd4, 0x4f, 0x4f, 0xcd, 0x4b, 0x2d, 0xce, 0x2c, 0xd6, 0x2b, 0x28, 0xca, 0x2f, 0xc9,
@@ -99,12 +99,12 @@ var fileDescriptor_6241c21661288629 = []byte{
0xb5, 0x7a, 0x01, 0x60, 0x55, 0x4e, 0x2c, 0x27, 0xee, 0xc9, 0x33, 0x04, 0x41, 0xf5, 0x08, 0x49,
0x73, 0x71, 0x26, 0xe5, 0xe4, 0x27, 0x67, 0xc7, 0xa7, 0x27, 0x16, 0x4b, 0x30, 0x2b, 0x30, 0x6a,
0xb0, 0x04, 0x71, 0x80, 0x05, 0xdc, 0x13, 0x8b, 0xbd, 0x58, 0x38, 0x98, 0x04, 0x98, 0x83, 0x38,
0x92, 0x12, 0x8b, 0x53, 0xe3, 0xd3, 0x52, 0x53, 0x9d, 0xdc, 0x4f, 0x3c, 0x92, 0x63, 0xbc, 0xf0,
0x92, 0x12, 0x8b, 0x53, 0xe3, 0xd3, 0x52, 0x53, 0x9d, 0xdc, 0x4e, 0x3c, 0x92, 0x63, 0xbc, 0xf0,
0x48, 0x8e, 0xf1, 0xc1, 0x23, 0x39, 0xc6, 0x09, 0x8f, 0xe5, 0x18, 0x2e, 0x3c, 0x96, 0x63, 0xb8,
0xf1, 0x58, 0x8e, 0x21, 0x4a, 0x37, 0x3d, 0xb3, 0x24, 0xa3, 0x34, 0x49, 0x2f, 0x39, 0x3f, 0x57,
0x3f, 0x39, 0xb5, 0x28, 0x59, 0x37, 0x33, 0x5f, 0x3f, 0x27, 0x31, 0x39, 0x3f, 0x2f, 0x33, 0x39,
0x45, 0xbf, 0x02, 0xc9, 0x43, 0x25, 0x95, 0x05, 0xa9, 0xc5, 0x49, 0x6c, 0x60, 0xaf, 0x18, 0x03,
0x02, 0x00, 0x00, 0xff, 0xff, 0x77, 0x0a, 0xa1, 0x73, 0x48, 0x01, 0x00, 0x00,
0xf1, 0x58, 0x8e, 0x21, 0x4a, 0x27, 0x3d, 0xb3, 0x24, 0xa3, 0x34, 0x49, 0x2f, 0x39, 0x3f, 0x57,
0x3f, 0xb5, 0x2c, 0x37, 0xbf, 0x58, 0x1f, 0xe1, 0x9b, 0x0a, 0x24, 0xff, 0x94, 0x54, 0x16, 0xa4,
0x16, 0x27, 0xb1, 0x81, 0x7d, 0x62, 0x0c, 0x08, 0x00, 0x00, 0xff, 0xff, 0x9c, 0xda, 0x93, 0xcb,
0x47, 0x01, 0x00, 0x00,
}
func (m *GenesisState) Marshal() (dAtA []byte, err error) {
+16 -3
View File
@@ -10,15 +10,28 @@ const (
// RouterKey uses module name for routing
RouterKey = ModuleName
// TransientKey is the key to access the FeeMarket transient store, that is reset
// during the Commit phase.
TransientKey = "transient_" + ModuleName
)
// prefix bytes for the feemarket persistent store
const (
prefixBlockGasUsed = iota + 1
deprecatedPrefixBaseFee // nolint
prefixBlockGasWanted = iota + 1
deprecatedPrefixBaseFee //nolint
)
const (
prefixTransientBlockGasUsed = iota + 1
)
// KVStore key prefixes
var (
KeyPrefixBlockGasUsed = []byte{prefixBlockGasUsed}
KeyPrefixBlockGasWanted = []byte{prefixBlockGasWanted}
)
// Transient Store key prefixes
var (
KeyPrefixTransientBlockGasWanted = []byte{prefixTransientBlockGasUsed}
)
+72 -5
View File
@@ -3,6 +3,7 @@ package types
import (
"fmt"
sdkmath "cosmossdk.io/math"
sdk "github.com/cosmos/cosmos-sdk/types"
paramtypes "github.com/cosmos/cosmos-sdk/x/params/types"
"github.com/ethereum/go-ethereum/params"
@@ -17,6 +18,15 @@ var (
ParamStoreKeyElasticityMultiplier = []byte("ElasticityMultiplier")
ParamStoreKeyBaseFee = []byte("BaseFee")
ParamStoreKeyEnableHeight = []byte("EnableHeight")
ParamStoreKeyMinGasPrice = []byte("MinGasPrice")
ParamStoreKeyMinGasMultiplier = []byte("MinGasMultiplier")
)
var (
// DefaultMinGasMultiplier is 0.5 or 50%
DefaultMinGasMultiplier = sdk.NewDecWithPrec(50, 2)
// DefaultMinGasPrice is 0 (i.e disabled)
DefaultMinGasPrice = sdk.ZeroDec()
)
// ParamKeyTable returns the parameter key table.
@@ -25,13 +35,23 @@ func ParamKeyTable() paramtypes.KeyTable {
}
// NewParams creates a new Params instance
func NewParams(noBaseFee bool, baseFeeChangeDenom, elasticityMultiplier uint32, baseFee uint64, enableHeight int64) Params {
func NewParams(
noBaseFee bool,
baseFeeChangeDenom,
elasticityMultiplier uint32,
baseFee uint64,
enableHeight int64,
minGasPrice sdk.Dec,
minGasPriceMultiplier sdk.Dec,
) Params {
return Params{
NoBaseFee: noBaseFee,
BaseFeeChangeDenominator: baseFeeChangeDenom,
ElasticityMultiplier: elasticityMultiplier,
BaseFee: sdk.NewIntFromUint64(baseFee),
BaseFee: sdkmath.NewIntFromUint64(baseFee),
EnableHeight: enableHeight,
MinGasPrice: minGasPrice,
MinGasMultiplier: minGasPriceMultiplier,
}
}
@@ -41,8 +61,10 @@ func DefaultParams() Params {
NoBaseFee: false,
BaseFeeChangeDenominator: params.BaseFeeChangeDenominator,
ElasticityMultiplier: params.ElasticityMultiplier,
BaseFee: sdk.NewIntFromUint64(params.InitialBaseFee),
BaseFee: sdkmath.NewIntFromUint64(params.InitialBaseFee),
EnableHeight: 0,
MinGasPrice: DefaultMinGasPrice,
MinGasMultiplier: DefaultMinGasMultiplier,
}
}
@@ -54,6 +76,8 @@ func (p *Params) ParamSetPairs() paramtypes.ParamSetPairs {
paramtypes.NewParamSetPair(ParamStoreKeyElasticityMultiplier, &p.ElasticityMultiplier, validateElasticityMultiplier),
paramtypes.NewParamSetPair(ParamStoreKeyBaseFee, &p.BaseFee, validateBaseFee),
paramtypes.NewParamSetPair(ParamStoreKeyEnableHeight, &p.EnableHeight, validateEnableHeight),
paramtypes.NewParamSetPair(ParamStoreKeyMinGasPrice, &p.MinGasPrice, validateMinGasPrice),
paramtypes.NewParamSetPair(ParamStoreKeyMinGasMultiplier, &p.MinGasMultiplier, validateMinGasPrice),
}
}
@@ -71,7 +95,11 @@ func (p Params) Validate() error {
return fmt.Errorf("enable height cannot be negative: %d", p.EnableHeight)
}
return nil
if err := validateMinGasMultiplier(p.MinGasMultiplier); err != nil {
return err
}
return validateMinGasPrice(p.MinGasPrice)
}
func (p *Params) IsBaseFeeEnabled(height int64) bool {
@@ -108,7 +136,7 @@ func validateElasticityMultiplier(i interface{}) error {
}
func validateBaseFee(i interface{}) error {
value, ok := i.(sdk.Int)
value, ok := i.(sdkmath.Int)
if !ok {
return fmt.Errorf("invalid parameter type: %T", i)
}
@@ -132,3 +160,42 @@ func validateEnableHeight(i interface{}) error {
return nil
}
func validateMinGasPrice(i interface{}) error {
v, ok := i.(sdk.Dec)
if !ok {
return fmt.Errorf("invalid parameter type: %T", i)
}
if v.IsNil() {
return fmt.Errorf("invalid parameter: nil")
}
if v.IsNegative() {
return fmt.Errorf("value cannot be negative: %s", i)
}
return nil
}
func validateMinGasMultiplier(i interface{}) error {
v, ok := i.(sdk.Dec)
if !ok {
return fmt.Errorf("invalid parameter type: %T", i)
}
if v.IsNil() {
return fmt.Errorf("invalid parameter: nil")
}
if v.IsNegative() {
return fmt.Errorf("value cannot be negative: %s", v)
}
if v.GT(sdk.OneDec()) {
return fmt.Errorf("value cannot be greater than 1: %s", v)
}
return nil
}
+59 -6
View File
@@ -1,11 +1,13 @@
package types
import (
sdk "github.com/cosmos/cosmos-sdk/types"
"testing"
paramtypes "github.com/cosmos/cosmos-sdk/x/params/types"
sdkmath "cosmossdk.io/math"
"github.com/stretchr/testify/suite"
sdk "github.com/cosmos/cosmos-sdk/types"
paramtypes "github.com/cosmos/cosmos-sdk/x/params/types"
)
type ParamsTestSuite struct {
@@ -29,7 +31,7 @@ func (suite *ParamsTestSuite) TestParamsValidate() {
{"default", DefaultParams(), false},
{
"valid",
NewParams(true, 7, 3, 2000000000, int64(544435345345435345)),
NewParams(true, 7, 3, 2000000000, int64(544435345345435345), sdk.NewDecWithPrec(20, 4), DefaultMinGasMultiplier),
false,
},
{
@@ -39,7 +41,27 @@ func (suite *ParamsTestSuite) TestParamsValidate() {
},
{
"base fee change denominator is 0 ",
NewParams(true, 0, 3, 2000000000, int64(544435345345435345)),
NewParams(true, 0, 3, 2000000000, int64(544435345345435345), sdk.NewDecWithPrec(20, 4), DefaultMinGasMultiplier),
true,
},
{
"invalid: min gas price negative",
NewParams(true, 7, 3, 2000000000, int64(544435345345435345), sdk.NewDecFromInt(sdkmath.NewInt(-1)), DefaultMinGasMultiplier),
true,
},
{
"valid: min gas multiplier zero",
NewParams(true, 7, 3, 2000000000, int64(544435345345435345), DefaultMinGasPrice, sdk.ZeroDec()),
false,
},
{
"invalid: min gas multiplier is negative",
NewParams(true, 7, 3, 2000000000, int64(544435345345435345), DefaultMinGasPrice, sdk.NewDecWithPrec(-5, 1)),
true,
},
{
"invalid: min gas multiplier bigger than 1",
NewParams(true, 7, 3, 2000000000, int64(544435345345435345), sdk.NewDecWithPrec(20, 4), sdk.NewDec(2)),
true,
},
}
@@ -65,9 +87,40 @@ func (suite *ParamsTestSuite) TestParamsValidatePriv() {
suite.Require().NoError(validateElasticityMultiplier(uint32(2)))
suite.Require().Error(validateBaseFee(""))
suite.Require().Error(validateBaseFee(int64(2000000000)))
suite.Require().Error(validateBaseFee(sdk.NewInt(-2000000000)))
suite.Require().NoError(validateBaseFee(sdk.NewInt(2000000000)))
suite.Require().Error(validateBaseFee(sdkmath.NewInt(-2000000000)))
suite.Require().NoError(validateBaseFee(sdkmath.NewInt(2000000000)))
suite.Require().Error(validateEnableHeight(""))
suite.Require().Error(validateEnableHeight(int64(-544435345345435345)))
suite.Require().NoError(validateEnableHeight(int64(544435345345435345)))
suite.Require().Error(validateMinGasPrice(sdk.Dec{}))
suite.Require().Error(validateMinGasMultiplier(sdk.NewDec(-5)))
suite.Require().Error(validateMinGasMultiplier(sdk.Dec{}))
suite.Require().Error(validateMinGasMultiplier(""))
}
func (suite *ParamsTestSuite) TestParamsValidateMinGasPrice() {
testCases := []struct {
name string
value interface{}
expError bool
}{
{"default", DefaultParams().MinGasPrice, false},
{"valid", sdk.NewDecFromInt(sdkmath.NewInt(1)), false},
{"invalid - wrong type - bool", false, true},
{"invalid - wrong type - string", "", true},
{"invalid - wrong type - int64", int64(123), true},
{"invalid - wrong type - sdkmath.Int", sdkmath.NewInt(1), true},
{"invalid - is nil", nil, true},
{"invalid - is negative", sdk.NewDecFromInt(sdkmath.NewInt(-1)), true},
}
for _, tc := range testCases {
err := validateMinGasPrice(tc.value)
if tc.expError {
suite.Require().Error(err, tc.name)
} else {
suite.Require().NoError(err, tc.name)
}
}
}
+29 -30
View File
@@ -286,36 +286,35 @@ func init() {
}
var fileDescriptor_71a07c1ffd85fde2 = []byte{
// 454 bytes of a gzipped FileDescriptorProto
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x8c, 0x93, 0x31, 0x6f, 0xd3, 0x40,
0x14, 0xc7, 0x7d, 0x04, 0xd2, 0x72, 0x2c, 0xe8, 0x48, 0xab, 0xca, 0x14, 0xb7, 0x32, 0x52, 0x05,
0x05, 0xfb, 0xd4, 0xb2, 0x32, 0x59, 0x82, 0x8a, 0x0d, 0xcc, 0x86, 0x84, 0xaa, 0xb3, 0xfb, 0xe2,
0x58, 0x89, 0x7d, 0x8e, 0xef, 0x12, 0x91, 0x15, 0x16, 0x06, 0x06, 0x24, 0x3e, 0x04, 0x5f, 0x25,
0x63, 0x24, 0x16, 0xc4, 0x10, 0xa1, 0x84, 0x0f, 0x82, 0x7c, 0x3e, 0x87, 0x98, 0x24, 0x90, 0x29,
0xa7, 0x97, 0xdf, 0xfd, 0xff, 0xff, 0xf7, 0xde, 0x19, 0xdb, 0x20, 0x3b, 0x90, 0x27, 0x71, 0x2a,
0x69, 0x1b, 0x20, 0x61, 0x79, 0x17, 0x24, 0x1d, 0x9e, 0xd1, 0xfe, 0x00, 0xf2, 0x91, 0x9b, 0xe5,
0x5c, 0x72, 0xb2, 0xbf, 0x60, 0xdc, 0x05, 0xe3, 0x0e, 0xcf, 0xcc, 0x56, 0xc4, 0x23, 0xae, 0x10,
0x5a, 0x9c, 0x4a, 0xda, 0x3c, 0x8c, 0x38, 0x8f, 0x7a, 0x40, 0x59, 0x16, 0x53, 0x96, 0xa6, 0x5c,
0x32, 0x19, 0xf3, 0x54, 0xe8, 0x7f, 0x4f, 0x36, 0xf8, 0xfd, 0x11, 0x56, 0x9c, 0xdd, 0xc2, 0xe4,
0x55, 0x11, 0xe1, 0x25, 0xcb, 0x59, 0x22, 0x7c, 0xe8, 0x0f, 0x40, 0x48, 0xfb, 0x35, 0xbe, 0x53,
0xab, 0x8a, 0x8c, 0xa7, 0x02, 0xc8, 0x53, 0xdc, 0xcc, 0x54, 0xe5, 0x00, 0x1d, 0xa3, 0x07, 0xb7,
0xce, 0x2d, 0x77, 0x7d, 0x62, 0xb7, 0xbc, 0xe7, 0x5d, 0x1f, 0x4f, 0x8f, 0x0c, 0x5f, 0xdf, 0xb1,
0xf7, 0xb4, 0xa8, 0xc7, 0x04, 0x3c, 0x07, 0xa8, 0xbc, 0xde, 0xe2, 0x56, 0xbd, 0xac, 0xcd, 0x9e,
0xe1, 0xdd, 0x80, 0x09, 0xb8, 0x6c, 0x03, 0x28, 0xbb, 0x9b, 0xde, 0xe9, 0x8f, 0xe9, 0xd1, 0x49,
0x14, 0xcb, 0xce, 0x20, 0x70, 0x43, 0x9e, 0xd0, 0x90, 0x8b, 0x84, 0x0b, 0xfd, 0xe3, 0x88, 0xab,
0x2e, 0x95, 0xa3, 0x0c, 0x84, 0xfb, 0x22, 0x95, 0xfe, 0x4e, 0x50, 0xca, 0xd9, 0xfb, 0x95, 0x7c,
0x8f, 0x87, 0xdd, 0x0b, 0xb6, 0x68, 0xf1, 0x21, 0xde, 0xfb, 0xab, 0xae, 0x7d, 0x6f, 0xe3, 0x46,
0xc4, 0xca, 0x0e, 0x1b, 0x7e, 0x71, 0x3c, 0xff, 0xda, 0xc0, 0x37, 0x14, 0x4b, 0x3e, 0x20, 0xdc,
0x2c, 0x7b, 0x23, 0xa7, 0x9b, 0x7a, 0x5f, 0x1d, 0xa7, 0xf9, 0x68, 0x2b, 0xb6, 0xf4, 0xb7, 0x8f,
0xdf, 0x7f, 0xfb, 0xf5, 0xe5, 0x9a, 0x49, 0x0e, 0x96, 0x16, 0x07, 0xc3, 0xa4, 0x58, 0x5e, 0x39,
0x48, 0xf2, 0x11, 0xe1, 0x1d, 0x3d, 0x2d, 0xf2, 0x6f, 0xe9, 0xfa, 0xa8, 0xcd, 0xc7, 0xdb, 0xc1,
0x3a, 0x88, 0xad, 0x82, 0x1c, 0x12, 0x73, 0x35, 0x48, 0xb5, 0x18, 0xf2, 0x09, 0xe1, 0xdd, 0x6a,
0x82, 0xe4, 0x3f, 0xf2, 0xf5, 0x05, 0x98, 0xce, 0x96, 0xb4, 0x4e, 0x73, 0x5f, 0xa5, 0xb9, 0x47,
0xee, 0xae, 0x49, 0x53, 0xb0, 0x97, 0x11, 0x13, 0xde, 0xc5, 0x78, 0x66, 0xa1, 0xc9, 0xcc, 0x42,
0x3f, 0x67, 0x16, 0xfa, 0x3c, 0xb7, 0x8c, 0xc9, 0xdc, 0x32, 0xbe, 0xcf, 0x2d, 0xe3, 0x8d, 0xb3,
0xfc, 0x6e, 0x20, 0x0f, 0x9d, 0x98, 0xd3, 0x1e, 0x0b, 0x79, 0x1a, 0x87, 0x57, 0xf4, 0xdd, 0x92,
0xa6, 0x7a, 0x42, 0x41, 0x53, 0x7d, 0x1d, 0x4f, 0x7e, 0x07, 0x00, 0x00, 0xff, 0xff, 0xe1, 0xc2,
0xfa, 0x4c, 0xb7, 0x03, 0x00, 0x00,
// 443 bytes of a gzipped FileDescriptorProto
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x8c, 0x53, 0xc1, 0x6e, 0xd3, 0x40,
0x10, 0xf5, 0x12, 0x48, 0xcb, 0x72, 0x41, 0x4b, 0x5a, 0x21, 0x0b, 0x6d, 0x83, 0x91, 0xa2, 0xb6,
0xb4, 0x5e, 0xb5, 0x5c, 0x39, 0x59, 0xa2, 0x88, 0x1b, 0x98, 0x1b, 0x12, 0xaa, 0xd6, 0x61, 0xea,
0x58, 0x89, 0xbd, 0x8e, 0x77, 0x13, 0x91, 0x2b, 0x37, 0x2e, 0x08, 0xc1, 0xd7, 0xf0, 0x07, 0x39,
0x46, 0xe2, 0x82, 0x38, 0x44, 0x28, 0xe1, 0x43, 0x90, 0xd7, 0xeb, 0x24, 0x06, 0x0c, 0x39, 0x65,
0x35, 0x79, 0xf3, 0xde, 0x9b, 0x37, 0x63, 0xec, 0x80, 0xea, 0x41, 0x16, 0x47, 0x89, 0x62, 0x57,
0x00, 0x31, 0xcf, 0xfa, 0xa0, 0xd8, 0xf8, 0x8c, 0x0d, 0x47, 0x90, 0x4d, 0xdc, 0x34, 0x13, 0x4a,
0x90, 0xfd, 0x15, 0xc6, 0x5d, 0x61, 0xdc, 0xf1, 0x99, 0xdd, 0x0a, 0x45, 0x28, 0x34, 0x84, 0xe5,
0xaf, 0x02, 0x6d, 0xdf, 0x0b, 0x85, 0x08, 0x07, 0xc0, 0x78, 0x1a, 0x31, 0x9e, 0x24, 0x42, 0x71,
0x15, 0x89, 0x44, 0x9a, 0x7f, 0x3b, 0x35, 0x7a, 0x6b, 0x62, 0x8d, 0x73, 0x5a, 0x98, 0xbc, 0xc8,
0x2d, 0x3c, 0xe7, 0x19, 0x8f, 0xa5, 0x0f, 0xc3, 0x11, 0x48, 0xe5, 0xbc, 0xc4, 0x77, 0x2a, 0x55,
0x99, 0x8a, 0x44, 0x02, 0x79, 0x8c, 0x9b, 0xa9, 0xae, 0xdc, 0x45, 0x6d, 0x74, 0x78, 0xeb, 0x9c,
0xba, 0x7f, 0x77, 0xec, 0x16, 0x7d, 0xde, 0xf5, 0xe9, 0xfc, 0xc0, 0xf2, 0x4d, 0x8f, 0xb3, 0x67,
0x48, 0x3d, 0x2e, 0xe1, 0x02, 0xa0, 0xd4, 0x7a, 0x8d, 0x5b, 0xd5, 0xb2, 0x11, 0x7b, 0x82, 0x77,
0x03, 0x2e, 0xe1, 0xf2, 0x0a, 0x40, 0xcb, 0xdd, 0xf4, 0x8e, 0xbf, 0xcf, 0x0f, 0x3a, 0x61, 0xa4,
0x7a, 0xa3, 0xc0, 0xed, 0x8a, 0x98, 0x75, 0x85, 0x8c, 0x85, 0x34, 0x3f, 0xa7, 0xf2, 0x4d, 0x9f,
0xa9, 0x49, 0x0a, 0xd2, 0x7d, 0x96, 0x28, 0x7f, 0x27, 0x28, 0xe8, 0x9c, 0xfd, 0x92, 0x7e, 0x20,
0xba, 0xfd, 0xa7, 0x7c, 0x35, 0xe2, 0x11, 0xde, 0xfb, 0xad, 0x6e, 0x74, 0x6f, 0xe3, 0x46, 0xc8,
0x8b, 0x09, 0x1b, 0x7e, 0xfe, 0x3c, 0xff, 0xd2, 0xc0, 0x37, 0x34, 0x96, 0xbc, 0x47, 0xb8, 0x59,
0xcc, 0x46, 0x8e, 0xeb, 0x66, 0xff, 0x33, 0x4e, 0xfb, 0xe1, 0x56, 0xd8, 0x42, 0xdf, 0xe9, 0xbc,
0xfb, 0xfa, 0xf3, 0xf3, 0xb5, 0x36, 0xa1, 0xac, 0x66, 0x85, 0x45, 0x9c, 0xe4, 0x03, 0xc2, 0x3b,
0x26, 0x33, 0xf2, 0x6f, 0x81, 0x6a, 0xe0, 0xf6, 0xc9, 0x76, 0x60, 0x63, 0xe7, 0x50, 0xdb, 0x71,
0x48, 0xbb, 0xce, 0x4e, 0xb9, 0x24, 0xf2, 0x09, 0xe1, 0xdd, 0x32, 0x4d, 0xf2, 0x1f, 0x91, 0xea,
0x32, 0xec, 0xd3, 0x2d, 0xd1, 0xc6, 0xd3, 0x91, 0xf6, 0xf4, 0x80, 0xdc, 0xaf, 0xf5, 0x94, 0x77,
0x5c, 0x86, 0x5c, 0x7a, 0x17, 0xd3, 0x05, 0x45, 0xb3, 0x05, 0x45, 0x3f, 0x16, 0x14, 0x7d, 0x5c,
0x52, 0x6b, 0xb6, 0xa4, 0xd6, 0xb7, 0x25, 0xb5, 0x5e, 0x9d, 0x6c, 0x5c, 0x12, 0x8c, 0xf3, 0x43,
0x5a, 0x93, 0xbd, 0xdd, 0xa0, 0xd3, 0x37, 0x15, 0x34, 0xf5, 0xe7, 0xf2, 0xe8, 0x57, 0x00, 0x00,
0x00, 0xff, 0xff, 0xe7, 0x66, 0xdc, 0x9f, 0xc8, 0x03, 0x00, 0x00,
}
// Reference imports to suppress errors if they are not otherwise used.
+3 -3
View File
@@ -256,11 +256,11 @@ func RegisterQueryHandlerClient(ctx context.Context, mux *runtime.ServeMux, clie
}
var (
pattern_Query_Params_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 2, 3}, []string{"feemarket", "evm", "v1", "params"}, "", runtime.AssumeColonVerbOpt(true)))
pattern_Query_Params_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 2, 3}, []string{"ethermint", "feemarket", "v1", "params"}, "", runtime.AssumeColonVerbOpt(true)))
pattern_Query_BaseFee_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 2, 3}, []string{"feemarket", "evm", "v1", "base_fee"}, "", runtime.AssumeColonVerbOpt(true)))
pattern_Query_BaseFee_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 2, 3}, []string{"ethermint", "feemarket", "v1", "base_fee"}, "", runtime.AssumeColonVerbOpt(true)))
pattern_Query_BlockGas_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 2, 3}, []string{"feemarket", "evm", "v1", "block_gas"}, "", runtime.AssumeColonVerbOpt(true)))
pattern_Query_BlockGas_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 2, 3}, []string{"ethermint", "feemarket", "v1", "block_gas"}, "", runtime.AssumeColonVerbOpt(true)))
)
var (