forked from cerc-io/laconicd-deprecated
update fork
This commit is contained in:
@@ -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)),
|
||||
))
|
||||
}
|
||||
|
||||
@@ -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)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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)
|
||||
}
|
||||
|
||||
@@ -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,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),
|
||||
|
||||
@@ -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{})
|
||||
|
||||
@@ -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), ðtypes.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), ðtypes.AccessList{}}
|
||||
}),
|
||||
Entry("dynamic tx with GasFeeCap > MinGasPrices, EffectivePrice < MinGasPrices", func() txParams {
|
||||
return txParams{nil, big.NewInt(minGasPrices + 10_000_000_000), big.NewInt(0), ðtypes.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), ðtypes.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), ðtypes.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), ðtypes.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), ðtypes.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), ðtypes.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), ðtypes.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), ðtypes.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), ðtypes.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, ðtypes.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), ðtypes.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), ðtypes.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
|
||||
}
|
||||
@@ -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)
|
||||
}
|
||||
|
||||
@@ -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)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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)
|
||||
}
|
||||
|
||||
@@ -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, ¶ms)
|
||||
// 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))
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user