forked from cerc-io/laconicd-deprecated
feemarket: global MinGasPrice
parameter (#1104)
* Add min_gas_price to feemarket params * Add MinGasPriceDecorators * feemarket integration tests for MinGasPrice * Restructure integration tests * Simplify integration tests context We use DeliverTx context to set up the app, otherwise not all settings are initialized. We test CheckTx with `s.app.BaseApp.CheckTx(req)`, which uses the `CheckTx` mode and context. * Update MinGasPrice spec in feemarket module * reorder ethermint module order for initializing genesis * feemarket migrations for adding MinGasPrice param * update changelog * Additional unit tests for MinGasPrice = 0, tx gas price > 0 (PR review) https://github.com/tharsis/ethermint/pull/1104#discussion_r884991661 * Use 0 MinGasPrice for transaction simulations * Fix duplicate registration of feemarket GenesisState and Params (PR review) https://github.com/tharsis/ethermint/pull/1104#issuecomment-1141893712
This commit is contained in:
parent
5533beed71
commit
046cd00174
@ -40,6 +40,7 @@ Ref: https://keepachangelog.com/en/1.0.0/
|
||||
|
||||
### API Breaking
|
||||
|
||||
- (feemarket) [tharsis#1104](https://github.com/tharsis/ethermint/pull/1104) Enforce a minimum gas price for Cosmos and EVM transactions through the `MinGasPrice` parameter.
|
||||
- (rpc) [tharsis#1081](https://github.com/tharsis/ethermint/pull/1081) Deduplicate some json-rpc logic codes, cleanup several dead functions.
|
||||
- (ante) [tharsis#1062](https://github.com/tharsis/ethermint/pull/1062) Emit event of eth tx hash in ante handler to support query failed transactions.
|
||||
|
||||
|
114
app/ante/fees.go
Normal file
114
app/ante/fees.go
Normal file
@ -0,0 +1,114 @@
|
||||
package ante
|
||||
|
||||
import (
|
||||
sdk "github.com/cosmos/cosmos-sdk/types"
|
||||
sdkerrors "github.com/cosmos/cosmos-sdk/types/errors"
|
||||
|
||||
ethtypes "github.com/ethereum/go-ethereum/core/types"
|
||||
evmtypes "github.com/tharsis/ethermint/x/evm/types"
|
||||
)
|
||||
|
||||
// MinGasPriceDecorator will check if the transaction's fee is at least as large
|
||||
// as the MinGasPrices param. If fee is too low, decorator returns error and tx
|
||||
// is rejected. This applies for both CheckTx and DeliverTx
|
||||
// If fee is high enough, then call next AnteHandler
|
||||
// CONTRACT: Tx must implement FeeTx to use MinGasPriceDecorator
|
||||
type MinGasPriceDecorator struct {
|
||||
feesKeeper FeeMarketKeeper
|
||||
evmKeeper EVMKeeper
|
||||
}
|
||||
|
||||
func NewMinGasPriceDecorator(fk FeeMarketKeeper, ek EVMKeeper) MinGasPriceDecorator {
|
||||
return MinGasPriceDecorator{feesKeeper: fk, evmKeeper: ek}
|
||||
}
|
||||
|
||||
func (mpd MinGasPriceDecorator) AnteHandle(ctx sdk.Context, tx sdk.Tx, simulate bool, next sdk.AnteHandler) (newCtx sdk.Context, err error) {
|
||||
minGasPrice := mpd.feesKeeper.GetParams(ctx).MinGasPrice
|
||||
minGasPrices := sdk.DecCoins{sdk.DecCoin{
|
||||
Denom: mpd.evmKeeper.GetParams(ctx).EvmDenom,
|
||||
Amount: minGasPrice,
|
||||
}}
|
||||
|
||||
feeTx, ok := tx.(sdk.FeeTx)
|
||||
if !ok {
|
||||
return ctx, sdkerrors.Wrap(sdkerrors.ErrTxDecode, "Tx must be a FeeTx")
|
||||
}
|
||||
|
||||
feeCoins := feeTx.GetFee()
|
||||
gas := feeTx.GetGas()
|
||||
|
||||
if !minGasPrices.IsZero() {
|
||||
requiredFees := make(sdk.Coins, len(minGasPrices))
|
||||
|
||||
// Determine the required fees by multiplying each required minimum gas
|
||||
// price by the gas limit, where fee = ceil(minGasPrice * gasLimit).
|
||||
gasLimit := sdk.NewDec(int64(gas))
|
||||
for i, gp := range minGasPrices {
|
||||
fee := gp.Amount.Mul(gasLimit)
|
||||
requiredFees[i] = sdk.NewCoin(gp.Denom, fee.Ceil().RoundInt())
|
||||
}
|
||||
|
||||
if !feeCoins.IsAnyGTE(requiredFees) {
|
||||
return ctx, sdkerrors.Wrapf(sdkerrors.ErrInsufficientFee, "provided fee < minimum global fee (%s < %s). Please increase the gas price.", feeCoins, requiredFees)
|
||||
}
|
||||
}
|
||||
|
||||
return next(ctx, tx, simulate)
|
||||
}
|
||||
|
||||
// EthMinGasPriceDecorator will check if the transaction's fee is at least as large
|
||||
// as the MinGasPrices param. If fee is too low, decorator returns error and tx
|
||||
// is rejected. This applies to both CheckTx and DeliverTx and regardless
|
||||
// if London hard fork or fee market params (EIP-1559) are enabled.
|
||||
// If fee is high enough, then call next AnteHandler
|
||||
type EthMinGasPriceDecorator struct {
|
||||
feesKeeper FeeMarketKeeper
|
||||
evmKeeper EVMKeeper
|
||||
}
|
||||
|
||||
func NewEthMinGasPriceDecorator(fk FeeMarketKeeper, ek EVMKeeper) EthMinGasPriceDecorator {
|
||||
return EthMinGasPriceDecorator{feesKeeper: fk, evmKeeper: ek}
|
||||
}
|
||||
|
||||
func (empd EthMinGasPriceDecorator) AnteHandle(ctx sdk.Context, tx sdk.Tx, simulate bool, next sdk.AnteHandler) (newCtx sdk.Context, err error) {
|
||||
minGasPrice := empd.feesKeeper.GetParams(ctx).MinGasPrice
|
||||
|
||||
if !minGasPrice.IsZero() {
|
||||
for _, msg := range tx.GetMsgs() {
|
||||
ethMsg, ok := msg.(*evmtypes.MsgEthereumTx)
|
||||
if !ok {
|
||||
return ctx, sdkerrors.Wrapf(sdkerrors.ErrUnknownRequest, "invalid message type %T, expected %T", msg, (*evmtypes.MsgEthereumTx)(nil))
|
||||
}
|
||||
|
||||
feeAmt := ethMsg.GetFee()
|
||||
|
||||
// For dynamic transactions, GetFee() uses the GasFeeCap value, which
|
||||
// is the maximum gas price that the signer can pay. In practice, the
|
||||
// signer can pay less, if the block's BaseFee is lower. So, in this case,
|
||||
// we use the EffectiveFee. If the feemarket formula results in a BaseFee
|
||||
// that lowers EffectivePrice until it is < MinGasPrices, the users must
|
||||
// increase the GasTipCap (priority fee) until EffectivePrice > MinGasPrices.
|
||||
// Transactions with MinGasPrices * gasUsed < tx fees < EffectiveFee are rejected
|
||||
// by the feemarket AnteHandle
|
||||
txData, err := evmtypes.UnpackTxData(ethMsg.Data)
|
||||
if err != nil {
|
||||
return ctx, sdkerrors.Wrapf(err, "failed to unpack tx data %s", ethMsg.Hash)
|
||||
}
|
||||
if txData.TxType() != ethtypes.LegacyTxType {
|
||||
paramsEvm := empd.evmKeeper.GetParams(ctx)
|
||||
ethCfg := paramsEvm.ChainConfig.EthereumConfig(empd.evmKeeper.ChainID())
|
||||
baseFee := empd.evmKeeper.GetBaseFee(ctx, ethCfg)
|
||||
feeAmt = ethMsg.GetEffectiveFee(baseFee)
|
||||
}
|
||||
|
||||
gasLimit := sdk.NewDec(int64(ethMsg.GetGas()))
|
||||
requiredFee := minGasPrice.Mul(gasLimit)
|
||||
|
||||
if sdk.NewDecFromBigInt(feeAmt).LT(requiredFee) {
|
||||
return ctx, sdkerrors.Wrapf(sdkerrors.ErrInsufficientFee, "provided fee < minimum global fee (%s < %s). Please increase the priority tip (for EIP-1559 txs) or the gas prices (for access list or legacy txs)", feeAmt, requiredFee)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return next(ctx, tx, simulate)
|
||||
}
|
339
app/ante/fees_test.go
Normal file
339
app/ante/fees_test.go
Normal file
@ -0,0 +1,339 @@
|
||||
package ante_test
|
||||
|
||||
import (
|
||||
"math/big"
|
||||
|
||||
sdk "github.com/cosmos/cosmos-sdk/types"
|
||||
banktypes "github.com/cosmos/cosmos-sdk/x/bank/types"
|
||||
ethtypes "github.com/ethereum/go-ethereum/core/types"
|
||||
"github.com/tharsis/ethermint/app/ante"
|
||||
"github.com/tharsis/ethermint/tests"
|
||||
evmtypes "github.com/tharsis/ethermint/x/evm/types"
|
||||
)
|
||||
|
||||
var execTypes = []struct {
|
||||
name string
|
||||
isCheckTx bool
|
||||
simulate bool
|
||||
}{
|
||||
{"deliverTx", false, false},
|
||||
{"deliverTxSimulate", false, true},
|
||||
}
|
||||
|
||||
func (s AnteTestSuite) TestMinGasPriceDecorator() {
|
||||
denom := evmtypes.DefaultEVMDenom
|
||||
testMsg := banktypes.MsgSend{
|
||||
FromAddress: "evmos1x8fhpj9nmhqk8z9kpgjt95ck2xwyue0ptzkucp",
|
||||
ToAddress: "evmos1dx67l23hz9l0k9hcher8xz04uj7wf3yu26l2yn",
|
||||
Amount: sdk.Coins{sdk.Coin{Amount: sdk.NewInt(10), Denom: denom}},
|
||||
}
|
||||
|
||||
testCases := []struct {
|
||||
name string
|
||||
malleate func() sdk.Tx
|
||||
expPass bool
|
||||
errMsg string
|
||||
}{
|
||||
{
|
||||
"invalid cosmos tx type",
|
||||
func() sdk.Tx {
|
||||
return &invalidTx{}
|
||||
},
|
||||
false,
|
||||
"must be a FeeTx",
|
||||
},
|
||||
{
|
||||
"valid cosmos tx with MinGasPrices = 0, gasPrice = 0",
|
||||
func() sdk.Tx {
|
||||
params := s.app.FeeMarketKeeper.GetParams(s.ctx)
|
||||
params.MinGasPrice = sdk.ZeroDec()
|
||||
s.app.FeeMarketKeeper.SetParams(s.ctx, params)
|
||||
|
||||
txBuilder := s.CreateTestCosmosTxBuilder(sdk.NewInt(0), denom, &testMsg)
|
||||
return txBuilder.GetTx()
|
||||
},
|
||||
true,
|
||||
"",
|
||||
},
|
||||
{
|
||||
"valid cosmos tx with MinGasPrices = 0, gasPrice > 0",
|
||||
func() sdk.Tx {
|
||||
params := s.app.FeeMarketKeeper.GetParams(s.ctx)
|
||||
params.MinGasPrice = sdk.ZeroDec()
|
||||
s.app.FeeMarketKeeper.SetParams(s.ctx, params)
|
||||
|
||||
txBuilder := s.CreateTestCosmosTxBuilder(sdk.NewInt(10), denom, &testMsg)
|
||||
return txBuilder.GetTx()
|
||||
},
|
||||
true,
|
||||
"",
|
||||
},
|
||||
{
|
||||
"valid cosmos tx with MinGasPrices = 10, gasPrice = 10",
|
||||
func() sdk.Tx {
|
||||
params := s.app.FeeMarketKeeper.GetParams(s.ctx)
|
||||
params.MinGasPrice = sdk.NewDec(10)
|
||||
s.app.FeeMarketKeeper.SetParams(s.ctx, params)
|
||||
|
||||
txBuilder := s.CreateTestCosmosTxBuilder(sdk.NewInt(10), denom, &testMsg)
|
||||
return txBuilder.GetTx()
|
||||
},
|
||||
true,
|
||||
"",
|
||||
},
|
||||
{
|
||||
"invalid cosmos tx with MinGasPrices = 10, gasPrice = 0",
|
||||
func() sdk.Tx {
|
||||
params := s.app.FeeMarketKeeper.GetParams(s.ctx)
|
||||
params.MinGasPrice = sdk.NewDec(10)
|
||||
s.app.FeeMarketKeeper.SetParams(s.ctx, params)
|
||||
|
||||
txBuilder := s.CreateTestCosmosTxBuilder(sdk.NewInt(0), denom, &testMsg)
|
||||
return txBuilder.GetTx()
|
||||
},
|
||||
false,
|
||||
"provided fee < minimum global fee",
|
||||
},
|
||||
{
|
||||
"invalid cosmos tx with wrong denom",
|
||||
func() sdk.Tx {
|
||||
params := s.app.FeeMarketKeeper.GetParams(s.ctx)
|
||||
params.MinGasPrice = sdk.NewDec(10)
|
||||
s.app.FeeMarketKeeper.SetParams(s.ctx, params)
|
||||
|
||||
txBuilder := s.CreateTestCosmosTxBuilder(sdk.NewInt(10), "stake", &testMsg)
|
||||
return txBuilder.GetTx()
|
||||
},
|
||||
false,
|
||||
"provided fee < minimum global fee",
|
||||
},
|
||||
}
|
||||
|
||||
for _, et := range execTypes {
|
||||
for _, tc := range testCases {
|
||||
s.Run(et.name+"_"+tc.name, func() {
|
||||
// s.SetupTest(et.isCheckTx)
|
||||
ctx := s.ctx.WithIsReCheckTx(et.isCheckTx)
|
||||
dec := ante.NewMinGasPriceDecorator(s.app.FeeMarketKeeper, s.app.EvmKeeper)
|
||||
_, err := dec.AnteHandle(ctx, tc.malleate(), et.simulate, nextFn)
|
||||
|
||||
if tc.expPass {
|
||||
s.Require().NoError(err, tc.name)
|
||||
} else {
|
||||
s.Require().Error(err, tc.name)
|
||||
s.Require().Contains(err.Error(), tc.errMsg, tc.name)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (s AnteTestSuite) TestEthMinGasPriceDecorator() {
|
||||
denom := evmtypes.DefaultEVMDenom
|
||||
from, privKey := tests.NewAddrKey()
|
||||
to := tests.GenerateAddress()
|
||||
emptyAccessList := ethtypes.AccessList{}
|
||||
|
||||
testCases := []struct {
|
||||
name string
|
||||
malleate func() sdk.Tx
|
||||
expPass bool
|
||||
errMsg string
|
||||
}{
|
||||
{
|
||||
"invalid tx type",
|
||||
func() sdk.Tx {
|
||||
params := s.app.FeeMarketKeeper.GetParams(s.ctx)
|
||||
params.MinGasPrice = sdk.NewDec(10)
|
||||
s.app.FeeMarketKeeper.SetParams(s.ctx, params)
|
||||
return &invalidTx{}
|
||||
},
|
||||
false,
|
||||
"invalid message type",
|
||||
},
|
||||
{
|
||||
"wrong tx type",
|
||||
func() sdk.Tx {
|
||||
params := s.app.FeeMarketKeeper.GetParams(s.ctx)
|
||||
params.MinGasPrice = sdk.NewDec(10)
|
||||
s.app.FeeMarketKeeper.SetParams(s.ctx, params)
|
||||
testMsg := banktypes.MsgSend{
|
||||
FromAddress: "evmos1x8fhpj9nmhqk8z9kpgjt95ck2xwyue0ptzkucp",
|
||||
ToAddress: "evmos1dx67l23hz9l0k9hcher8xz04uj7wf3yu26l2yn",
|
||||
Amount: sdk.Coins{sdk.Coin{Amount: sdk.NewInt(10), Denom: denom}},
|
||||
}
|
||||
txBuilder := s.CreateTestCosmosTxBuilder(sdk.NewInt(0), denom, &testMsg)
|
||||
return txBuilder.GetTx()
|
||||
},
|
||||
false,
|
||||
"invalid message type",
|
||||
},
|
||||
{
|
||||
"valid: invalid tx type with MinGasPrices = 0",
|
||||
func() sdk.Tx {
|
||||
params := s.app.FeeMarketKeeper.GetParams(s.ctx)
|
||||
params.MinGasPrice = sdk.ZeroDec()
|
||||
s.app.FeeMarketKeeper.SetParams(s.ctx, params)
|
||||
return &invalidTx{}
|
||||
},
|
||||
true,
|
||||
"",
|
||||
},
|
||||
{
|
||||
"valid legacy tx with MinGasPrices = 0, gasPrice = 0",
|
||||
func() sdk.Tx {
|
||||
params := s.app.FeeMarketKeeper.GetParams(s.ctx)
|
||||
params.MinGasPrice = sdk.ZeroDec()
|
||||
s.app.FeeMarketKeeper.SetParams(s.ctx, params)
|
||||
|
||||
msg := s.BuildTestEthTx(from, to, nil, make([]byte, 0), big.NewInt(0), nil, nil, nil)
|
||||
return s.CreateTestTx(msg, privKey, 1, false)
|
||||
},
|
||||
true,
|
||||
"",
|
||||
},
|
||||
{
|
||||
"valid legacy tx with MinGasPrices = 0, gasPrice > 0",
|
||||
func() sdk.Tx {
|
||||
params := s.app.FeeMarketKeeper.GetParams(s.ctx)
|
||||
params.MinGasPrice = sdk.ZeroDec()
|
||||
s.app.FeeMarketKeeper.SetParams(s.ctx, params)
|
||||
|
||||
msg := s.BuildTestEthTx(from, to, nil, make([]byte, 0), big.NewInt(10), nil, nil, nil)
|
||||
return s.CreateTestTx(msg, privKey, 1, false)
|
||||
},
|
||||
true,
|
||||
"",
|
||||
},
|
||||
{
|
||||
"valid legacy tx with MinGasPrices = 10, gasPrice = 10",
|
||||
func() sdk.Tx {
|
||||
params := s.app.FeeMarketKeeper.GetParams(s.ctx)
|
||||
params.MinGasPrice = sdk.NewDec(10)
|
||||
s.app.FeeMarketKeeper.SetParams(s.ctx, params)
|
||||
|
||||
msg := s.BuildTestEthTx(from, to, nil, make([]byte, 0), big.NewInt(10), nil, nil, nil)
|
||||
return s.CreateTestTx(msg, privKey, 1, false)
|
||||
},
|
||||
true,
|
||||
"",
|
||||
},
|
||||
{
|
||||
"invalid legacy tx with MinGasPrices = 10, gasPrice = 0",
|
||||
func() sdk.Tx {
|
||||
params := s.app.FeeMarketKeeper.GetParams(s.ctx)
|
||||
params.MinGasPrice = sdk.NewDec(10)
|
||||
s.app.FeeMarketKeeper.SetParams(s.ctx, params)
|
||||
|
||||
msg := s.BuildTestEthTx(from, to, nil, make([]byte, 0), big.NewInt(0), nil, nil, nil)
|
||||
return s.CreateTestTx(msg, privKey, 1, false)
|
||||
},
|
||||
false,
|
||||
"provided fee < minimum global fee",
|
||||
},
|
||||
{
|
||||
"valid dynamic tx with MinGasPrices = 0, EffectivePrice = 0",
|
||||
func() sdk.Tx {
|
||||
params := s.app.FeeMarketKeeper.GetParams(s.ctx)
|
||||
params.MinGasPrice = sdk.ZeroDec()
|
||||
s.app.FeeMarketKeeper.SetParams(s.ctx, params)
|
||||
|
||||
msg := s.BuildTestEthTx(from, to, nil, make([]byte, 0), nil, big.NewInt(0), big.NewInt(0), &emptyAccessList)
|
||||
return s.CreateTestTx(msg, privKey, 1, false)
|
||||
},
|
||||
true,
|
||||
"",
|
||||
},
|
||||
{
|
||||
"valid dynamic tx with MinGasPrices = 0, EffectivePrice > 0",
|
||||
func() sdk.Tx {
|
||||
params := s.app.FeeMarketKeeper.GetParams(s.ctx)
|
||||
params.MinGasPrice = sdk.ZeroDec()
|
||||
s.app.FeeMarketKeeper.SetParams(s.ctx, params)
|
||||
|
||||
msg := s.BuildTestEthTx(from, to, nil, make([]byte, 0), nil, big.NewInt(100), big.NewInt(50), &emptyAccessList)
|
||||
return s.CreateTestTx(msg, privKey, 1, false)
|
||||
},
|
||||
true,
|
||||
"",
|
||||
},
|
||||
{
|
||||
"valid dynamic tx with MinGasPrices < EffectivePrice",
|
||||
func() sdk.Tx {
|
||||
params := s.app.FeeMarketKeeper.GetParams(s.ctx)
|
||||
params.MinGasPrice = sdk.NewDec(10)
|
||||
s.app.FeeMarketKeeper.SetParams(s.ctx, params)
|
||||
|
||||
msg := s.BuildTestEthTx(from, to, nil, make([]byte, 0), nil, big.NewInt(100), big.NewInt(100), &emptyAccessList)
|
||||
return s.CreateTestTx(msg, privKey, 1, false)
|
||||
},
|
||||
true,
|
||||
"",
|
||||
},
|
||||
{
|
||||
"invalid dynamic tx with MinGasPrices > EffectivePrice",
|
||||
func() sdk.Tx {
|
||||
params := s.app.FeeMarketKeeper.GetParams(s.ctx)
|
||||
params.MinGasPrice = sdk.NewDec(10)
|
||||
s.app.FeeMarketKeeper.SetParams(s.ctx, params)
|
||||
|
||||
msg := s.BuildTestEthTx(from, to, nil, make([]byte, 0), nil, big.NewInt(0), big.NewInt(0), &emptyAccessList)
|
||||
return s.CreateTestTx(msg, privKey, 1, false)
|
||||
},
|
||||
false,
|
||||
"provided fee < minimum global fee",
|
||||
},
|
||||
{
|
||||
"invalid dynamic tx with MinGasPrices > BaseFee, MinGasPrices > EffectivePrice",
|
||||
func() sdk.Tx {
|
||||
params := s.app.FeeMarketKeeper.GetParams(s.ctx)
|
||||
params.MinGasPrice = sdk.NewDec(100)
|
||||
s.app.FeeMarketKeeper.SetParams(s.ctx, params)
|
||||
|
||||
feemarketParams := s.app.FeeMarketKeeper.GetParams(s.ctx)
|
||||
feemarketParams.BaseFee = sdk.NewInt(10)
|
||||
s.app.FeeMarketKeeper.SetParams(s.ctx, feemarketParams)
|
||||
|
||||
msg := s.BuildTestEthTx(from, to, nil, make([]byte, 0), nil, big.NewInt(1000), big.NewInt(0), &emptyAccessList)
|
||||
return s.CreateTestTx(msg, privKey, 1, false)
|
||||
},
|
||||
false,
|
||||
"provided fee < minimum global fee",
|
||||
},
|
||||
{
|
||||
"valid dynamic tx with MinGasPrices > BaseFee, MinGasPrices < EffectivePrice (big GasTipCap)",
|
||||
func() sdk.Tx {
|
||||
params := s.app.FeeMarketKeeper.GetParams(s.ctx)
|
||||
params.MinGasPrice = sdk.NewDec(100)
|
||||
s.app.FeeMarketKeeper.SetParams(s.ctx, params)
|
||||
|
||||
feemarketParams := s.app.FeeMarketKeeper.GetParams(s.ctx)
|
||||
feemarketParams.BaseFee = sdk.NewInt(10)
|
||||
s.app.FeeMarketKeeper.SetParams(s.ctx, feemarketParams)
|
||||
|
||||
msg := s.BuildTestEthTx(from, to, nil, make([]byte, 0), nil, big.NewInt(1000), big.NewInt(101), &emptyAccessList)
|
||||
return s.CreateTestTx(msg, privKey, 1, false)
|
||||
},
|
||||
true,
|
||||
"",
|
||||
},
|
||||
}
|
||||
|
||||
for _, et := range execTypes {
|
||||
for _, tc := range testCases {
|
||||
s.Run(et.name+"_"+tc.name, func() {
|
||||
// s.SetupTest(et.isCheckTx)
|
||||
s.SetupTest()
|
||||
dec := ante.NewEthMinGasPriceDecorator(s.app.FeeMarketKeeper, s.app.EvmKeeper)
|
||||
_, err := dec.AnteHandle(s.ctx, tc.malleate(), et.simulate, nextFn)
|
||||
|
||||
if tc.expPass {
|
||||
s.Require().NoError(err, tc.name)
|
||||
} else {
|
||||
s.Require().Error(err, tc.name)
|
||||
s.Require().Contains(err.Error(), tc.errMsg, tc.name)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
@ -49,8 +49,9 @@ func (options HandlerOptions) Validate() error {
|
||||
|
||||
func newEthAnteHandler(options HandlerOptions) sdk.AnteHandler {
|
||||
return sdk.ChainAnteDecorators(
|
||||
NewEthSetUpContextDecorator(options.EvmKeeper), // outermost AnteDecorator. SetUpContext must be called first
|
||||
NewEthMempoolFeeDecorator(options.EvmKeeper), // Check eth effective gas price against minimal-gas-prices
|
||||
NewEthSetUpContextDecorator(options.EvmKeeper), // outermost AnteDecorator. SetUpContext must be called first
|
||||
NewEthMempoolFeeDecorator(options.EvmKeeper), // Check eth effective gas price against minimal-gas-prices
|
||||
NewEthMinGasPriceDecorator(options.FeeMarketKeeper, options.EvmKeeper), // Check eth effective gas price against the global MinGasPrice
|
||||
NewEthValidateBasicDecorator(options.EvmKeeper),
|
||||
NewEthSigVerificationDecorator(options.EvmKeeper),
|
||||
NewEthAccountVerificationDecorator(options.AccountKeeper, options.EvmKeeper),
|
||||
@ -67,6 +68,7 @@ func newCosmosAnteHandler(options HandlerOptions) sdk.AnteHandler {
|
||||
ante.NewSetUpContextDecorator(),
|
||||
ante.NewRejectExtensionOptionsDecorator(),
|
||||
ante.NewMempoolFeeDecorator(),
|
||||
NewMinGasPriceDecorator(options.FeeMarketKeeper, options.EvmKeeper),
|
||||
ante.NewValidateBasicDecorator(),
|
||||
ante.NewTxTimeoutHeightDecorator(),
|
||||
ante.NewValidateMemoDecorator(options.AccountKeeper),
|
||||
@ -89,6 +91,7 @@ func newCosmosAnteHandlerEip712(options HandlerOptions) sdk.AnteHandler {
|
||||
// NOTE: extensions option decorator removed
|
||||
// ante.NewRejectExtensionOptionsDecorator(),
|
||||
ante.NewMempoolFeeDecorator(),
|
||||
NewMinGasPriceDecorator(options.FeeMarketKeeper, options.EvmKeeper),
|
||||
ante.NewValidateBasicDecorator(),
|
||||
ante.NewTxTimeoutHeightDecorator(),
|
||||
ante.NewValidateMemoDecorator(options.AccountKeeper),
|
||||
|
@ -11,6 +11,7 @@ import (
|
||||
"github.com/ethereum/go-ethereum/params"
|
||||
"github.com/tharsis/ethermint/x/evm/statedb"
|
||||
evmtypes "github.com/tharsis/ethermint/x/evm/types"
|
||||
feemarkettypes "github.com/tharsis/ethermint/x/feemarket/types"
|
||||
)
|
||||
|
||||
// EVMKeeper defines the expected keeper interface used on the Eth AnteHandler
|
||||
@ -32,3 +33,8 @@ type EVMKeeper interface {
|
||||
type protoTxProvider interface {
|
||||
GetProtoTx() *tx.Tx
|
||||
}
|
||||
|
||||
// FeeMarketKeeper defines the expected keeper interface used on the AnteHandler
|
||||
type FeeMarketKeeper interface {
|
||||
GetParams(ctx sdk.Context) (params feemarkettypes.Params)
|
||||
}
|
||||
|
@ -2,6 +2,7 @@ package ante_test
|
||||
|
||||
import (
|
||||
"math"
|
||||
"math/big"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
@ -123,6 +124,38 @@ func TestAnteTestSuite(t *testing.T) {
|
||||
})
|
||||
}
|
||||
|
||||
func (s *AnteTestSuite) BuildTestEthTx(
|
||||
from common.Address,
|
||||
to common.Address,
|
||||
amount *big.Int,
|
||||
input []byte,
|
||||
gasPrice *big.Int,
|
||||
gasFeeCap *big.Int,
|
||||
gasTipCap *big.Int,
|
||||
accesses *ethtypes.AccessList,
|
||||
) *evmtypes.MsgEthereumTx {
|
||||
chainID := s.app.EvmKeeper.ChainID()
|
||||
nonce := s.app.EvmKeeper.GetNonce(
|
||||
s.ctx,
|
||||
common.BytesToAddress(from.Bytes()),
|
||||
)
|
||||
gasLimit := uint64(100000)
|
||||
msgEthereumTx := evmtypes.NewTx(
|
||||
chainID,
|
||||
nonce,
|
||||
&to,
|
||||
amount,
|
||||
gasLimit,
|
||||
gasPrice,
|
||||
gasFeeCap,
|
||||
gasTipCap,
|
||||
input,
|
||||
accesses,
|
||||
)
|
||||
msgEthereumTx.From = from.String()
|
||||
return msgEthereumTx
|
||||
}
|
||||
|
||||
// CreateTestTx is a helper function to create a tx given multiple inputs.
|
||||
func (suite *AnteTestSuite) CreateTestTx(
|
||||
msg *evmtypes.MsgEthereumTx, priv cryptotypes.PrivKey, accNum uint64, signCosmosTx bool,
|
||||
@ -203,6 +236,18 @@ func (suite *AnteTestSuite) CreateTestTxBuilder(
|
||||
return txBuilder
|
||||
}
|
||||
|
||||
func (suite *AnteTestSuite) CreateTestCosmosTxBuilder(gasPrice sdk.Int, denom string, msgs ...sdk.Msg) client.TxBuilder {
|
||||
gasLimit := uint64(1000000)
|
||||
txBuilder := suite.clientCtx.TxConfig.NewTxBuilder()
|
||||
|
||||
txBuilder.SetGasLimit(gasLimit)
|
||||
fees := &sdk.Coins{{Denom: denom, Amount: gasPrice.MulRaw(int64(gasLimit))}}
|
||||
txBuilder.SetFeeAmount(*fees)
|
||||
err := txBuilder.SetMsgs(msgs...)
|
||||
suite.Require().NoError(err)
|
||||
return txBuilder
|
||||
}
|
||||
|
||||
func (suite *AnteTestSuite) CreateTestEIP712TxBuilderMsgSend(from sdk.AccAddress, priv cryptotypes.PrivKey, chainId string, gas uint64, gasAmount sdk.Coins) client.TxBuilder {
|
||||
// Build MsgSend
|
||||
recipient := sdk.AccAddress(common.Address{}.Bytes())
|
||||
|
@ -507,6 +507,11 @@ func NewEthermintApp(
|
||||
govtypes.ModuleName,
|
||||
minttypes.ModuleName,
|
||||
ibchost.ModuleName,
|
||||
// evm module denomination is used by the feemarket module, in AnteHandle
|
||||
evmtypes.ModuleName,
|
||||
// NOTE: feemarket need to be initialized before genutil module:
|
||||
// gentx transactions use MinGasPriceDecorator.AnteHandle
|
||||
feemarkettypes.ModuleName,
|
||||
genutiltypes.ModuleName,
|
||||
evidencetypes.ModuleName,
|
||||
ibctransfertypes.ModuleName,
|
||||
@ -515,10 +520,6 @@ func NewEthermintApp(
|
||||
paramstypes.ModuleName,
|
||||
upgradetypes.ModuleName,
|
||||
vestingtypes.ModuleName,
|
||||
// Ethermint modules
|
||||
evmtypes.ModuleName,
|
||||
feemarkettypes.ModuleName,
|
||||
|
||||
// NOTE: crisis module must go at the end to check for invariants on each module
|
||||
crisistypes.ModuleName,
|
||||
)
|
||||
|
@ -954,6 +954,7 @@ Params defines the EVM module parameters
|
||||
| `elasticity_multiplier` | [uint32](#uint32) | | elasticity multiplier bounds the maximum gas limit an EIP-1559 block may have. |
|
||||
| `enable_height` | [int64](#int64) | | height at which the base fee calculation is enabled. |
|
||||
| `base_fee` | [string](#string) | | base fee for EIP-1559 blocks. |
|
||||
| `min_gas_price` | [string](#string) | | min_gas_price defines the minimum gas price value for cosmos and eth transactions |
|
||||
|
||||
|
||||
|
||||
|
5
go.mod
5
go.mod
@ -19,7 +19,8 @@ require (
|
||||
github.com/holiman/uint256 v1.2.0
|
||||
github.com/improbable-eng/grpc-web v0.15.0
|
||||
github.com/miguelmota/go-ethereum-hdwallet v0.1.1
|
||||
github.com/onsi/ginkgo v1.16.5
|
||||
github.com/onsi/ginkgo/v2 v2.1.4
|
||||
github.com/onsi/gomega v1.19.0
|
||||
github.com/pkg/errors v0.9.1
|
||||
github.com/rakyll/statik v0.1.7
|
||||
github.com/regen-network/cosmos-proto v0.3.1
|
||||
@ -144,7 +145,7 @@ require (
|
||||
golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a // indirect
|
||||
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211 // indirect
|
||||
golang.org/x/text v0.3.7 // indirect
|
||||
golang.org/x/tools v0.1.5 // indirect
|
||||
golang.org/x/tools v0.1.10 // indirect
|
||||
gopkg.in/ini.v1 v1.66.4 // indirect
|
||||
gopkg.in/natefinch/npipe.v2 v2.0.0-20160621034901-c1b8fa8bdcce // indirect
|
||||
gopkg.in/olebedev/go-duktape.v3 v3.0.0-20200619000410-60c24ae608a6 // indirect
|
||||
|
19
go.sum
19
go.sum
@ -527,6 +527,7 @@ github.com/google/pprof v0.0.0-20201203190320-1bf35d6f28c2/go.mod h1:kpwsk12EmLe
|
||||
github.com/google/pprof v0.0.0-20201218002935-b9804c9f04c2/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE=
|
||||
github.com/google/pprof v0.0.0-20210122040257-d980be63207e/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE=
|
||||
github.com/google/pprof v0.0.0-20210226084205-cbba55b83ad5/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE=
|
||||
github.com/google/pprof v0.0.0-20210407192527-94a9f03dee38/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE=
|
||||
github.com/google/pprof v0.0.0-20210601050228-01bbb1931b22/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE=
|
||||
github.com/google/pprof v0.0.0-20210609004039-a478d1d731e9/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE=
|
||||
github.com/google/pprof v0.0.0-20210720184732-4bb14d4b1be1/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE=
|
||||
@ -871,15 +872,19 @@ github.com/onsi/ginkgo v1.7.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+W
|
||||
github.com/onsi/ginkgo v1.12.1/go.mod h1:zj2OWP4+oCPe1qIXoGWkgMRwljMUYCdkwsT2108oapk=
|
||||
github.com/onsi/ginkgo v1.14.0/go.mod h1:iSB4RoI2tjJc9BBv4NKIKWKya62Rps+oPG/Lv9klQyY=
|
||||
github.com/onsi/ginkgo v1.16.2/go.mod h1:CObGmKUOKaSC0RjmoAK7tKyn4Azo5P2IWuoMnvwxz1E=
|
||||
github.com/onsi/ginkgo v1.16.4 h1:29JGrr5oVBm5ulCWet69zQkzWipVXIol6ygQUe/EzNc=
|
||||
github.com/onsi/ginkgo v1.16.4/go.mod h1:dX+/inL/fNMqNlz0e9LfyB9TswhZpCVdJM/Z6Vvnwo0=
|
||||
github.com/onsi/ginkgo v1.16.5 h1:8xi0RTUf59SOSfEtZMvwTvXYMzG4gV23XVHOZiXNtnE=
|
||||
github.com/onsi/ginkgo v1.16.5/go.mod h1:+E8gABHa3K6zRBolWtd+ROzc/U5bkGt0FwiG042wbpU=
|
||||
github.com/onsi/ginkgo/v2 v2.1.3/go.mod h1:vw5CSIxN1JObi/U8gcbwft7ZxR2dgaR70JSE3/PpL4c=
|
||||
github.com/onsi/ginkgo/v2 v2.1.4 h1:GNapqRSid3zijZ9H77KrgVG4/8KqiyRsxcSxe+7ApXY=
|
||||
github.com/onsi/ginkgo/v2 v2.1.4/go.mod h1:um6tUpWM/cxCK3/FK8BXqEiUMUwRgSM4JXG47RKZmLU=
|
||||
github.com/onsi/gomega v1.4.1/go.mod h1:C1qb7wdrVGGVU+Z6iS04AVkA3Q65CEZX59MT0QO5uiA=
|
||||
github.com/onsi/gomega v1.4.3/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY=
|
||||
github.com/onsi/gomega v1.7.1/go.mod h1:XdKZgCCFLUoM/7CFJVPcG8C1xQ1AJ0vpAezJrB7JYyY=
|
||||
github.com/onsi/gomega v1.10.1/go.mod h1:iN09h71vgCQne3DLsj+A5owkum+a2tYe+TOCB1ybHNo=
|
||||
github.com/onsi/gomega v1.13.0 h1:7lLHu94wT9Ij0o6EWWclhu0aOh32VxhkwEJvzuWPeak=
|
||||
github.com/onsi/gomega v1.13.0/go.mod h1:lRk9szgn8TxENtWd0Tp4c3wjlRfMTMH27I+3Je41yGY=
|
||||
github.com/onsi/gomega v1.17.0/go.mod h1:HnhC7FXeEQY45zxNK3PPoIUhzk/80Xly9PcubAlGdZY=
|
||||
github.com/onsi/gomega v1.19.0 h1:4ieX6qQjPP/BfC3mpsAtIGGlxTWPeA3Inl/7DtXw1tw=
|
||||
github.com/onsi/gomega v1.19.0/go.mod h1:LY+I3pBVzYsTBU1AnDwOSxaYi9WoWiqgwooUqq9yPro=
|
||||
github.com/op/go-logging v0.0.0-20160315200505-970db520ece7/go.mod h1:HzydrMdWErDVzsI23lYNej1Htcns9BCg93Dk0bBINWk=
|
||||
github.com/opencontainers/go-digest v1.0.0-rc1/go.mod h1:cMLVZDEM3+U2I4VmLI6N8jQYUd2OVphdqWwCJHrFt2s=
|
||||
github.com/opencontainers/go-digest v1.0.0 h1:apOUWs51W5PlhuyGyz9FCeeBIOUDA/6nW8Oi/yOhh5U=
|
||||
@ -1187,6 +1192,7 @@ github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9de
|
||||
github.com/yuin/goldmark v1.1.32/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
|
||||
github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
|
||||
github.com/yuin/goldmark v1.3.5/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k=
|
||||
github.com/yuin/goldmark v1.4.1/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k=
|
||||
github.com/zondax/hid v0.9.0 h1:eiT3P6vNxAEVxXMw66eZUAAnU2zD33JBkfG/EnfAKl8=
|
||||
github.com/zondax/hid v0.9.0/go.mod h1:l5wttcP0jwtdLjqjMMWFVEE7d1zO0jvSPA9OPZxWpEM=
|
||||
go.etcd.io/bbolt v1.3.2/go.mod h1:IbVyRI1SCnLcuJnV2u8VeU0CEYM7e686BmAb1XKL+uU=
|
||||
@ -1264,6 +1270,7 @@ golang.org/x/crypto v0.0.0-20210421170649-83a5a9bb288b/go.mod h1:T9bdIzuCu7OtxOm
|
||||
golang.org/x/crypto v0.0.0-20210616213533-5ff15b29337e/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
|
||||
golang.org/x/crypto v0.0.0-20210817164053-32db794688a5/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
|
||||
golang.org/x/crypto v0.0.0-20210915214749-c084706c2272/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
|
||||
golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
|
||||
golang.org/x/crypto v0.0.0-20211108221036-ceb1ce70b4fa/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
|
||||
golang.org/x/crypto v0.0.0-20220411220226-7b82a4e95df4/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4=
|
||||
golang.org/x/crypto v0.0.0-20220518034528-6f7dac969898 h1:SLP7Q4Di66FONjDJbCYrCRrh97focO6sLogHO7/g8F0=
|
||||
@ -1311,6 +1318,7 @@ golang.org/x/mod v0.4.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
|
||||
golang.org/x/mod v0.4.1/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
|
||||
golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
|
||||
golang.org/x/mod v0.5.0/go.mod h1:5OXOZSfqPIIbmVBIIKWRFfZjPR0E5r58TLhUjH0a2Ro=
|
||||
golang.org/x/mod v0.6.0-dev.0.20220106191415-9b9b3d81d5e3/go.mod h1:3p9vT2HGsQu2K1YbXdKPJLVgG5VJdoTa1poYQBtP1AY=
|
||||
golang.org/x/net v0.0.0-20180719180050-a680a1efc54d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
@ -1372,6 +1380,7 @@ golang.org/x/net v0.0.0-20210805182204-aaa1db679c0d/go.mod h1:9nx3DQGgdP8bBQD5qx
|
||||
golang.org/x/net v0.0.0-20210813160813-60bc85c4be6d/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
|
||||
golang.org/x/net v0.0.0-20210903162142-ad29c8ab022f/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
|
||||
golang.org/x/net v0.0.0-20210917221730-978cfadd31cf/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
|
||||
golang.org/x/net v0.0.0-20211015210444-4f30a5c0130f/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
|
||||
golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
|
||||
golang.org/x/net v0.0.0-20211208012354-db4efeb81f4b/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
|
||||
golang.org/x/net v0.0.0-20220127200216-cd36cc0744dd/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk=
|
||||
@ -1518,6 +1527,7 @@ golang.org/x/sys v0.0.0-20210908233432-aa78b53d3365/go.mod h1:oPkhp1MJrh7nUepCBc
|
||||
golang.org/x/sys v0.0.0-20210917161153-d61c044b1678/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20210927094055-39ccf1dd6fa6/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20211007075335-d3039528d8ac/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20211019181941-9d821ace8654/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20211124211545-fe61309f8881/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20211205182925-97ca703d548d/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20211210111614-af8b64212486/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
@ -1620,8 +1630,9 @@ golang.org/x/tools v0.1.1/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk=
|
||||
golang.org/x/tools v0.1.2/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk=
|
||||
golang.org/x/tools v0.1.3/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk=
|
||||
golang.org/x/tools v0.1.4/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk=
|
||||
golang.org/x/tools v0.1.5 h1:ouewzE6p+/VEB31YYnTbEJdi8pFqKp4P4n85vwo3DHA=
|
||||
golang.org/x/tools v0.1.5/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk=
|
||||
golang.org/x/tools v0.1.10 h1:QjFRCZxdOhBJ/UNgnBZLbNV13DlbnK0quyivTnXJM20=
|
||||
golang.org/x/tools v0.1.10/go.mod h1:Uh6Zz+xoGYZom868N8YTex3t7RhtHDBrE8Gzo9bV56E=
|
||||
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
|
@ -25,4 +25,9 @@ message Params {
|
||||
(gogoproto.customtype) = "github.com/cosmos/cosmos-sdk/types.Int",
|
||||
(gogoproto.nullable) = false
|
||||
];
|
||||
// min_gas_price defines the minimum gas price value for cosmos and eth transactions
|
||||
string min_gas_price = 7 [
|
||||
(gogoproto.customtype) = "github.com/cosmos/cosmos-sdk/types.Dec",
|
||||
(gogoproto.nullable) = false
|
||||
];
|
||||
}
|
@ -15,7 +15,7 @@ import (
|
||||
sdk "github.com/cosmos/cosmos-sdk/types"
|
||||
evmtypes "github.com/tharsis/ethermint/x/evm/types"
|
||||
|
||||
// . "github.com/onsi/ginkgo"
|
||||
// . "github.com/onsi/ginkgo/v2"
|
||||
// . "github.com/onsi/gomega"
|
||||
|
||||
"github.com/stretchr/testify/suite"
|
||||
|
29
testutil/fund.go
Normal file
29
testutil/fund.go
Normal file
@ -0,0 +1,29 @@
|
||||
package testutil
|
||||
|
||||
import (
|
||||
sdk "github.com/cosmos/cosmos-sdk/types"
|
||||
bankkeeper "github.com/cosmos/cosmos-sdk/x/bank/keeper"
|
||||
evmtypes "github.com/tharsis/ethermint/x/evm/types"
|
||||
)
|
||||
|
||||
// FundAccount is a utility function that funds an account by minting and
|
||||
// sending the coins to the address. This should be used for testing purposes
|
||||
// only!
|
||||
func FundAccount(bankKeeper bankkeeper.Keeper, ctx sdk.Context, addr sdk.AccAddress, amounts sdk.Coins) error {
|
||||
if err := bankKeeper.MintCoins(ctx, evmtypes.ModuleName, amounts); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return bankKeeper.SendCoinsFromModuleToAccount(ctx, evmtypes.ModuleName, addr, amounts)
|
||||
}
|
||||
|
||||
// FundModuleAccount is a utility function that funds a module account by
|
||||
// minting and sending the coins to the address. This should be used for testing
|
||||
// purposes only!
|
||||
func FundModuleAccount(bankKeeper bankkeeper.Keeper, ctx sdk.Context, recipientMod string, amounts sdk.Coins) error {
|
||||
if err := bankKeeper.MintCoins(ctx, evmtypes.ModuleName, amounts); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return bankKeeper.SendCoinsFromModuleToModule(ctx, evmtypes.ModuleName, recipientMod, amounts)
|
||||
}
|
@ -3,7 +3,7 @@
|
||||
package tools
|
||||
|
||||
import (
|
||||
_ "github.com/onsi/ginkgo/ginkgo"
|
||||
_ "github.com/onsi/ginkgo/v2"
|
||||
)
|
||||
|
||||
// This file imports packages that are used when running go generate, or used
|
||||
|
655
x/feemarket/keeper/integration_test.go
Normal file
655
x/feemarket/keeper/integration_test.go
Normal file
@ -0,0 +1,655 @@
|
||||
package keeper_test
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"math/big"
|
||||
"strings"
|
||||
|
||||
. "github.com/onsi/ginkgo/v2"
|
||||
. "github.com/onsi/gomega"
|
||||
|
||||
"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"
|
||||
"github.com/tharsis/ethermint/app"
|
||||
"github.com/tharsis/ethermint/crypto/ethsecp256k1"
|
||||
"github.com/tharsis/ethermint/encoding"
|
||||
"github.com/tharsis/ethermint/tests"
|
||||
"github.com/tharsis/ethermint/testutil"
|
||||
"github.com/tharsis/ethermint/x/feemarket/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"
|
||||
evmtypes "github.com/tharsis/ethermint/x/evm/types"
|
||||
)
|
||||
|
||||
var _ = Describe("Ethermint App min gas prices settings: ", func() {
|
||||
var (
|
||||
privKey *ethsecp256k1.PrivKey
|
||||
address sdk.AccAddress
|
||||
msg banktypes.MsgSend
|
||||
)
|
||||
|
||||
var setupChain = func(cliMinGasPricesStr 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(cliMinGasPricesStr),
|
||||
)
|
||||
|
||||
genesisState := app.NewDefaultGenesisState()
|
||||
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: simapp.DefaultConsensusParams,
|
||||
},
|
||||
)
|
||||
|
||||
s.app = newapp
|
||||
s.SetupApp(false)
|
||||
}
|
||||
|
||||
var setupTest = func(cliMinGasPrices string) {
|
||||
setupChain(cliMinGasPrices)
|
||||
|
||||
privKey, address = generateKey()
|
||||
amount, ok := sdk.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: sdk.NewInt(10000),
|
||||
}},
|
||||
}
|
||||
s.Commit()
|
||||
}
|
||||
|
||||
var setupContext = func(cliMinGasPrice string, minGasPrice sdk.Dec) {
|
||||
setupTest(cliMinGasPrice + s.denom)
|
||||
params := types.DefaultParams()
|
||||
params.MinGasPrice = minGasPrice
|
||||
s.app.FeeMarketKeeper.SetParams(s.ctx, params)
|
||||
s.Commit()
|
||||
}
|
||||
|
||||
Context("with Cosmos transactions", func() {
|
||||
Context("min-gas-prices (local) < MinGasPrices (feemarket param)", func() {
|
||||
cliMinGasPrice := "1"
|
||||
minGasPrice := sdk.NewDecWithPrec(3, 0)
|
||||
BeforeEach(func() {
|
||||
setupContext(cliMinGasPrice, minGasPrice)
|
||||
})
|
||||
|
||||
Context("during CheckTx", func() {
|
||||
It("should reject transactions with gasPrice < MinGasPrices", func() {
|
||||
gasPrice := sdk.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 := sdk.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 := sdk.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 := sdk.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() {
|
||||
cliMinGasPrice := "3"
|
||||
minGasPrice := sdk.NewDecWithPrec(3, 0)
|
||||
BeforeEach(func() {
|
||||
setupContext(cliMinGasPrice, minGasPrice)
|
||||
})
|
||||
|
||||
Context("during CheckTx", func() {
|
||||
It("should reject transactions with gasPrice < min-gas-prices", func() {
|
||||
gasPrice := sdk.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 := sdk.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 := sdk.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 := sdk.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() {
|
||||
cliMinGasPrice := "5"
|
||||
minGasPrice := sdk.NewDecWithPrec(3, 0)
|
||||
BeforeEach(func() {
|
||||
setupContext(cliMinGasPrice, minGasPrice)
|
||||
})
|
||||
Context("during CheckTx", func() {
|
||||
It("should reject transactions with gasPrice < MinGasPrices", func() {
|
||||
gasPrice := sdk.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 < min-gas-prices", func() {
|
||||
gasPrice := sdk.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 > min-gas-prices", func() {
|
||||
gasPrice := sdk.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 := sdk.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 MinGasPrices < gasPrice < than min-gas-prices", func() {
|
||||
gasPrice := sdk.NewInt(4)
|
||||
res := deliverTx(privKey, &gasPrice, &msg)
|
||||
Expect(res.IsOK()).To(Equal(true), "transaction should have succeeded", res.GetLog())
|
||||
})
|
||||
|
||||
It("should accept transactions with gasPrice >= min-gas-prices", func() {
|
||||
gasPrice := sdk.NewInt(5)
|
||||
res := deliverTx(privKey, &gasPrice, &msg)
|
||||
Expect(res.IsOK()).To(Equal(true), "transaction should have succeeded", res.GetLog())
|
||||
})
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
Context("with EVM transactions", func() {
|
||||
type txParams struct {
|
||||
gasPrice *big.Int
|
||||
gasFeeCap *big.Int
|
||||
gasTipCap *big.Int
|
||||
accesses *ethtypes.AccessList
|
||||
}
|
||||
type getprices func() txParams
|
||||
|
||||
getBaseFee := func() int64 {
|
||||
paramsEvm := s.app.EvmKeeper.GetParams(s.ctx)
|
||||
ethCfg := paramsEvm.ChainConfig.EthereumConfig(s.app.EvmKeeper.ChainID())
|
||||
return s.app.EvmKeeper.GetBaseFee(s.ctx, ethCfg).Int64()
|
||||
}
|
||||
Context("with BaseFee (feemarket) < MinGasPrices (feemarket param)", func() {
|
||||
var baseFee int64
|
||||
BeforeEach(func() {
|
||||
baseFee = getBaseFee()
|
||||
setupContext("1", sdk.NewDecWithPrec(baseFee+30000000000, 0))
|
||||
})
|
||||
|
||||
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(baseFee + 20000000000), nil, nil, nil}
|
||||
}),
|
||||
Entry("dynamic tx", func() txParams {
|
||||
return txParams{nil, big.NewInt(baseFee + 20000000000), big.NewInt(0), ðtypes.AccessList{}}
|
||||
}),
|
||||
Entry("dynamic tx with GasFeeCap < MinGasPrices", func() txParams {
|
||||
return txParams{nil, big.NewInt(baseFee + 29000000000), big.NewInt(29000000000), ðtypes.AccessList{}}
|
||||
}),
|
||||
Entry("dynamic tx with GasFeeCap > MinGasPrices, EffectivePrice < MinGasPrices", func() txParams {
|
||||
return txParams{nil, big.NewInt(baseFee + 40000000000), 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(baseFee + 31000000000), nil, nil, nil}
|
||||
}),
|
||||
Entry("dynamic tx", func() txParams {
|
||||
return txParams{nil, big.NewInt(baseFee + 31000000000), big.NewInt(31000000000), ð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(baseFee + 20000000000), nil, nil, nil}
|
||||
}),
|
||||
Entry("dynamic tx", func() txParams {
|
||||
return txParams{nil, big.NewInt(baseFee + 20000000000), big.NewInt(0), ðtypes.AccessList{}}
|
||||
}),
|
||||
Entry("dynamic tx with GasFeeCap < MinGasPrices", func() txParams {
|
||||
return txParams{nil, big.NewInt(baseFee + 29000000000), big.NewInt(29000000000), ðtypes.AccessList{}}
|
||||
}),
|
||||
Entry("dynamic tx with GasFeeCap > MinGasPrices, EffectivePrice < MinGasPrices", func() txParams {
|
||||
return txParams{nil, big.NewInt(baseFee + 40000000000), 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 := 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 + 30000000001), nil, nil, nil}
|
||||
}),
|
||||
// the base fee decreases in this test, so we use a large gas tip
|
||||
// to maintain an EffectivePrice > MinGasPrices
|
||||
Entry("dynamic tx, EffectivePrice > MinGasPrices", func() txParams {
|
||||
return txParams{nil, big.NewInt(baseFee + 30000000001), big.NewInt(30000000001), ðtypes.AccessList{}}
|
||||
}),
|
||||
)
|
||||
})
|
||||
})
|
||||
|
||||
Context("with MinGasPrices (feemarket param) < BaseFee (feemarket)", func() {
|
||||
var baseFee int64
|
||||
BeforeEach(func() {
|
||||
baseFee = getBaseFee()
|
||||
s.Require().Greater(baseFee, int64(10))
|
||||
setupContext("5", sdk.NewDecWithPrec(10, 0))
|
||||
})
|
||||
|
||||
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(2), nil, nil, nil}
|
||||
}),
|
||||
Entry("dynamic tx", func() txParams {
|
||||
return txParams{nil, big.NewInt(2), big.NewInt(2), ð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(20), nil, nil, nil}
|
||||
}),
|
||||
Entry("dynamic tx", func() txParams {
|
||||
return txParams{nil, big.NewInt(baseFee - 1), big.NewInt(20), ð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 + 1000000000), nil, nil, nil}
|
||||
}),
|
||||
Entry("dynamic tx", func() txParams {
|
||||
return txParams{nil, big.NewInt(baseFee + 1000000000), big.NewInt(10), ð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(2), nil, nil, nil}
|
||||
}),
|
||||
Entry("dynamic tx", func() txParams {
|
||||
return txParams{nil, big.NewInt(2), big.NewInt(2), ð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())
|
||||
},
|
||||
Entry("legacy tx", func() txParams {
|
||||
return txParams{big.NewInt(20), nil, nil, nil}
|
||||
}),
|
||||
Entry("dynamic tx", func() txParams {
|
||||
return txParams{nil, big.NewInt(20), big.NewInt(20), ð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 + 10), nil, nil, nil}
|
||||
}),
|
||||
Entry("dynamic tx", func() txParams {
|
||||
return txParams{nil, big.NewInt(baseFee + 10), big.NewInt(10), ðtypes.AccessList{}}
|
||||
}),
|
||||
)
|
||||
})
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
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)
|
||||
|
||||
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: sdk.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 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 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 prepareCosmosTx(priv *ethsecp256k1.PrivKey, gasPrice *sdk.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 := sdk.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 deliverTx(priv *ethsecp256k1.PrivKey, gasPrice *sdk.Int, msgs ...sdk.Msg) abci.ResponseDeliverTx {
|
||||
bz := prepareCosmosTx(priv, gasPrice, msgs...)
|
||||
req := abci.RequestDeliverTx{Tx: bz}
|
||||
res := s.app.BaseApp.DeliverTx(req)
|
||||
return res
|
||||
}
|
||||
|
||||
func checkTx(priv *ethsecp256k1.PrivKey, gasPrice *sdk.Int, msgs ...sdk.Msg) abci.ResponseCheckTx {
|
||||
bz := prepareCosmosTx(priv, gasPrice, msgs...)
|
||||
req := abci.RequestCheckTx{Tx: bz}
|
||||
res := s.app.BaseApp.CheckTx(req)
|
||||
return res
|
||||
}
|
@ -6,6 +6,9 @@ import (
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
. "github.com/onsi/ginkgo/v2"
|
||||
. "github.com/onsi/gomega"
|
||||
|
||||
"github.com/stretchr/testify/require"
|
||||
"github.com/stretchr/testify/suite"
|
||||
|
||||
@ -15,6 +18,7 @@ import (
|
||||
"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/tharsis/ethermint/app"
|
||||
@ -22,12 +26,14 @@ import (
|
||||
"github.com/tharsis/ethermint/encoding"
|
||||
"github.com/tharsis/ethermint/tests"
|
||||
ethermint "github.com/tharsis/ethermint/types"
|
||||
evmtypes "github.com/tharsis/ethermint/x/evm/types"
|
||||
"github.com/tharsis/ethermint/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"
|
||||
@ -49,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)
|
||||
@ -66,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(checkTx, nil)
|
||||
suite.ctx = suite.app.BaseApp.NewContext(checkTx, tmproto.Header{
|
||||
Height: 1,
|
||||
ChainID: "ethermint_9000-1",
|
||||
@ -104,8 +126,10 @@ func (suite *KeeperTestSuite) DoSetupTest(t require.TestingT) {
|
||||
|
||||
valAddr := sdk.ValAddress(suite.address.Bytes())
|
||||
validator, err := stakingtypes.NewValidator(valAddr, priv.PubKey(), stakingtypes.Description{})
|
||||
err = suite.app.StakingKeeper.SetValidatorByConsAddr(suite.ctx, validator)
|
||||
require.NoError(t, err)
|
||||
validator = stakingkeeper.TestingUpdateValidator(suite.app.StakingKeeper, suite.ctx, validator, true)
|
||||
suite.app.StakingKeeper.AfterValidatorCreated(suite.ctx, validator.GetOperator())
|
||||
|
||||
err = suite.app.StakingKeeper.SetValidatorByConsAddr(suite.ctx, validator)
|
||||
require.NoError(t, err)
|
||||
suite.app.StakingKeeper.SetValidator(suite.ctx, validator)
|
||||
@ -114,14 +138,32 @@ func (suite *KeeperTestSuite) DoSetupTest(t require.TestingT) {
|
||||
suite.clientCtx = client.Context{}.WithTxConfig(encodingConfig.TxConfig)
|
||||
suite.ethSigner = ethtypes.LatestSignerForChainID(suite.app.EvmKeeper.ChainID())
|
||||
suite.appCodec = encodingConfig.Marshaler
|
||||
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() {
|
||||
|
@ -4,6 +4,7 @@ import (
|
||||
sdk "github.com/cosmos/cosmos-sdk/types"
|
||||
|
||||
v010 "github.com/tharsis/ethermint/x/feemarket/migrations/v010"
|
||||
v011 "github.com/tharsis/ethermint/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)
|
||||
}
|
||||
|
@ -6,8 +6,8 @@ import (
|
||||
sdk "github.com/cosmos/cosmos-sdk/types"
|
||||
|
||||
paramtypes "github.com/cosmos/cosmos-sdk/x/params/types"
|
||||
"github.com/tharsis/ethermint/x/feemarket/migrations/v010/types"
|
||||
v09types "github.com/tharsis/ethermint/x/feemarket/migrations/v09/types"
|
||||
"github.com/tharsis/ethermint/x/feemarket/types"
|
||||
)
|
||||
|
||||
// KeyPrefixBaseFeeV1 is the base fee key prefix used in version 1
|
||||
|
472
x/feemarket/migrations/v010/types/feemarket.pb.go
generated
Normal file
472
x/feemarket/migrations/v010/types/feemarket.pb.go
generated
Normal 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
x/feemarket/migrations/v010/types/genesis.pb.go
generated
Normal file
356
x/feemarket/migrations/v010/types/genesis.pb.go
generated
Normal 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")
|
||||
)
|
134
x/feemarket/migrations/v010/types/params.go
Normal file
134
x/feemarket/migrations/v010/types/params.go
Normal file
@ -0,0 +1,134 @@
|
||||
package types
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
sdk "github.com/cosmos/cosmos-sdk/types"
|
||||
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: sdk.NewIntFromUint64(baseFee),
|
||||
EnableHeight: enableHeight,
|
||||
}
|
||||
}
|
||||
|
||||
// DefaultParams returns default evm parameters
|
||||
func DefaultParams() Params {
|
||||
return Params{
|
||||
NoBaseFee: false,
|
||||
BaseFeeChangeDenominator: params.BaseFeeChangeDenominator,
|
||||
ElasticityMultiplier: params.ElasticityMultiplier,
|
||||
BaseFee: sdk.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.(sdk.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
|
||||
}
|
37
x/feemarket/migrations/v011/migrate.go
Normal file
37
x/feemarket/migrations/v011/migrate.go
Normal file
@ -0,0 +1,37 @@
|
||||
package v011
|
||||
|
||||
import (
|
||||
sdk "github.com/cosmos/cosmos-sdk/types"
|
||||
|
||||
paramtypes "github.com/cosmos/cosmos-sdk/x/params/types"
|
||||
v010types "github.com/tharsis/ethermint/x/feemarket/migrations/v010/types"
|
||||
"github.com/tharsis/ethermint/x/feemarket/types"
|
||||
)
|
||||
|
||||
// MigrateStore adds the MinGasPrice param with a value of 0
|
||||
func MigrateStore(ctx sdk.Context, paramstore *paramtypes.Subspace) error {
|
||||
if !paramstore.HasKeyTable() {
|
||||
ps := paramstore.WithKeyTable(types.ParamKeyTable())
|
||||
paramstore = &ps
|
||||
}
|
||||
|
||||
paramstore.Set(ctx, types.ParamStoreKeyMinGasPrice, sdk.ZeroDec())
|
||||
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
|
||||
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: sdk.ZeroDec(),
|
||||
},
|
||||
BlockGas: oldState.BlockGas,
|
||||
}
|
||||
}
|
73
x/feemarket/migrations/v011/migrate_test.go
Normal file
73
x/feemarket/migrations/v011/migrate_test.go
Normal file
@ -0,0 +1,73 @@
|
||||
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/tharsis/ethermint/encoding"
|
||||
|
||||
"github.com/tharsis/ethermint/app"
|
||||
v010types "github.com/tharsis/ethermint/x/feemarket/migrations/v010/types"
|
||||
v011 "github.com/tharsis/ethermint/x/feemarket/migrations/v011"
|
||||
feemarkettypes "github.com/tharsis/ethermint/x/feemarket/types"
|
||||
)
|
||||
|
||||
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.Marshaler, 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))
|
||||
|
||||
// Run migrations
|
||||
err := v011.MigrateStore(ctx, ¶mstore)
|
||||
require.NoError(t, err)
|
||||
|
||||
// Make sure the params are set
|
||||
require.True(t, paramstore.Has(ctx, feemarkettypes.ParamStoreKeyMinGasPrice))
|
||||
|
||||
var minGasPrice sdk.Dec
|
||||
|
||||
// Make sure the new params are set
|
||||
require.NotPanics(t, func() {
|
||||
paramstore.Get(ctx, feemarkettypes.ParamStoreKeyMinGasPrice, &minGasPrice)
|
||||
})
|
||||
|
||||
// check the params are updated
|
||||
require.True(t, minGasPrice.IsZero())
|
||||
}
|
||||
|
||||
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.Marshaler.UnmarshalJSON([]byte(rawJson), &genState)
|
||||
require.NoError(t, err)
|
||||
|
||||
migratedGenState := v011.MigrateJSON(genState)
|
||||
|
||||
require.True(t, migratedGenState.Params.MinGasPrice.IsZero())
|
||||
}
|
@ -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
|
||||
@ -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.
|
||||
|
@ -4,6 +4,7 @@ import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
|
||||
sdk "github.com/cosmos/cosmos-sdk/types"
|
||||
"github.com/cosmos/cosmos-sdk/types/module"
|
||||
|
||||
"github.com/tharsis/ethermint/x/feemarket/types"
|
||||
@ -11,7 +12,8 @@ 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())
|
||||
|
||||
blockGas := simState.Rand.Uint64()
|
||||
feemarketGenesis := types.NewGenesisState(params, blockGas)
|
||||
|
||||
|
@ -33,3 +33,6 @@ Transactions specify a maximum fee per gas they are willing to pay total (aka: m
|
||||
|
||||
Reference: [EIP1559](https://eips.ethereum.org/EIPS/eip-1559)
|
||||
|
||||
## Global Minimum Gas Price
|
||||
|
||||
The minimum gas price needed for transactions to be processed. It applies to both Cosmos and EVM transactions. Governance can change this `feemarket` module parameter value. If the effective gas price or the 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. If transactions are rejected due to having a gas price lower than `MinGasPrice`, users need to resend the transactions with a gas price higher than `MinGasPrice`. In the case of EIP-1559 (dynamic fee transactions), users must increase the priority fee for their transactions to be valid.
|
||||
|
@ -12,3 +12,4 @@ The `x/feemarket` module contains the following parameters:
|
||||
| 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 |
|
||||
| MinGasPrice | sdk.Dec | 0 | global minimum gas price that needs to be paid to include a transaction in a block |
|
||||
|
25
x/feemarket/spec/09_antehandlers.md
Normal file
25
x/feemarket/spec/09_antehandlers.md
Normal file
@ -0,0 +1,25 @@
|
||||
<!--
|
||||
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`.
|
||||
:::
|
96
x/feemarket/types/feemarket.pb.go
generated
96
x/feemarket/types/feemarket.pb.go
generated
@ -38,6 +38,8 @@ 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"`
|
||||
}
|
||||
|
||||
func (m *Params) Reset() { *m = Params{} }
|
||||
@ -110,29 +112,31 @@ func init() {
|
||||
}
|
||||
|
||||
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,
|
||||
// 371 bytes of a gzipped FileDescriptorProto
|
||||
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x94, 0x91, 0x4f, 0xeb, 0xda, 0x30,
|
||||
0x18, 0xc7, 0x9b, 0xdf, 0x1f, 0xff, 0xc4, 0x09, 0x52, 0xdc, 0x28, 0x1b, 0xd4, 0xb2, 0x81, 0xf4,
|
||||
0xb2, 0x16, 0xf1, 0xbc, 0x8b, 0x93, 0x4d, 0x07, 0x03, 0xe9, 0x71, 0x97, 0x90, 0xd6, 0xc7, 0x36,
|
||||
0xd8, 0x24, 0x25, 0x89, 0x32, 0xdf, 0xc5, 0x5e, 0x96, 0x47, 0x8f, 0x63, 0x07, 0x19, 0xfa, 0x26,
|
||||
0x76, 0x1c, 0x56, 0xd7, 0x7a, 0xdd, 0xa9, 0xcd, 0xf3, 0xf9, 0xe4, 0x79, 0x1e, 0xf2, 0xc5, 0x43,
|
||||
0x30, 0x19, 0x28, 0xce, 0x84, 0x09, 0x57, 0x00, 0x9c, 0xaa, 0x35, 0x98, 0x70, 0x3b, 0xaa, 0x0f,
|
||||
0x41, 0xa1, 0xa4, 0x91, 0xf6, 0xab, 0xca, 0x0b, 0x6a, 0xb4, 0x1d, 0xbd, 0xee, 0xa7, 0x32, 0x95,
|
||||
0xa5, 0x12, 0x5e, 0xfe, 0xae, 0xf6, 0xdb, 0x3f, 0x0f, 0xb8, 0xb1, 0xa0, 0x8a, 0x72, 0x6d, 0xbb,
|
||||
0xb8, 0x23, 0x24, 0x89, 0xa9, 0x06, 0xb2, 0x02, 0x70, 0x90, 0x87, 0xfc, 0x56, 0xd4, 0x16, 0x72,
|
||||
0x42, 0x35, 0x7c, 0x02, 0xb0, 0x3f, 0xe0, 0x37, 0xff, 0x20, 0x49, 0x32, 0x2a, 0x52, 0x20, 0x4b,
|
||||
0x10, 0x92, 0x33, 0x41, 0x8d, 0x54, 0xce, 0x83, 0x87, 0xfc, 0x6e, 0xe4, 0xc4, 0x57, 0xfb, 0x63,
|
||||
0x29, 0x4c, 0x6b, 0x6e, 0x8f, 0xf1, 0x4b, 0xc8, 0xa9, 0x36, 0x2c, 0x61, 0x66, 0x47, 0xf8, 0x26,
|
||||
0x37, 0xac, 0xc8, 0x19, 0x28, 0xe7, 0xb1, 0xbc, 0xd8, 0xaf, 0xe1, 0xd7, 0x8a, 0xd9, 0xef, 0x70,
|
||||
0x17, 0x04, 0x8d, 0x73, 0x20, 0x19, 0xb0, 0x34, 0x33, 0xce, 0xb3, 0x87, 0xfc, 0xc7, 0xe8, 0xc5,
|
||||
0xb5, 0x38, 0x2b, 0x6b, 0xf6, 0x1c, 0xb7, 0xaa, 0xad, 0x1b, 0x1e, 0xf2, 0xdb, 0x93, 0x60, 0x7f,
|
||||
0x1c, 0x58, 0xbf, 0x8e, 0x83, 0x61, 0xca, 0x4c, 0xb6, 0x89, 0x83, 0x44, 0xf2, 0x30, 0x91, 0x9a,
|
||||
0x4b, 0x7d, 0xfb, 0xbc, 0xd7, 0xcb, 0x75, 0x68, 0x76, 0x05, 0xe8, 0x60, 0x2e, 0x4c, 0xd4, 0xbc,
|
||||
0x6d, 0x6d, 0x47, 0xb8, 0xcb, 0x99, 0x20, 0x29, 0xd5, 0xa4, 0x50, 0x2c, 0x01, 0xa7, 0xf9, 0xdf,
|
||||
0xfd, 0xa6, 0x90, 0x44, 0x1d, 0xce, 0xc4, 0x67, 0xaa, 0x17, 0x97, 0x16, 0x5f, 0x9e, 0x5a, 0x4f,
|
||||
0xbd, 0xe7, 0xa8, 0xc7, 0x04, 0x33, 0x8c, 0xe6, 0xd5, 0x03, 0x4f, 0x66, 0xfb, 0x93, 0x8b, 0x0e,
|
||||
0x27, 0x17, 0xfd, 0x3e, 0xb9, 0xe8, 0xc7, 0xd9, 0xb5, 0x0e, 0x67, 0xd7, 0xfa, 0x79, 0x76, 0xad,
|
||||
0x6f, 0xc1, 0xdd, 0x18, 0x93, 0x51, 0xa5, 0x99, 0x0e, 0xeb, 0xf4, 0xbf, 0xdf, 0xe5, 0x5f, 0x8e,
|
||||
0x8c, 0x1b, 0x65, 0x96, 0xe3, 0xbf, 0x01, 0x00, 0x00, 0xff, 0xff, 0x3c, 0x5d, 0x33, 0x70, 0x23,
|
||||
0x02, 0x00, 0x00,
|
||||
}
|
||||
|
||||
func (m *Params) Marshal() (dAtA []byte, err error) {
|
||||
@ -155,6 +159,16 @@ func (m *Params) MarshalToSizedBuffer(dAtA []byte) (int, error) {
|
||||
_ = i
|
||||
var l int
|
||||
_ = l
|
||||
{
|
||||
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 +238,8 @@ 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))
|
||||
return n
|
||||
}
|
||||
|
||||
@ -373,6 +389,40 @@ 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
|
||||
default:
|
||||
iNdEx = preIndex
|
||||
skippy, err := skipFeemarket(dAtA[iNdEx:])
|
||||
|
@ -17,6 +17,7 @@ var (
|
||||
ParamStoreKeyElasticityMultiplier = []byte("ElasticityMultiplier")
|
||||
ParamStoreKeyBaseFee = []byte("BaseFee")
|
||||
ParamStoreKeyEnableHeight = []byte("EnableHeight")
|
||||
ParamStoreKeyMinGasPrice = []byte("MinGasPrice")
|
||||
)
|
||||
|
||||
// ParamKeyTable returns the parameter key table.
|
||||
@ -25,13 +26,21 @@ 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,
|
||||
) Params {
|
||||
return Params{
|
||||
NoBaseFee: noBaseFee,
|
||||
BaseFeeChangeDenominator: baseFeeChangeDenom,
|
||||
ElasticityMultiplier: elasticityMultiplier,
|
||||
BaseFee: sdk.NewIntFromUint64(baseFee),
|
||||
EnableHeight: enableHeight,
|
||||
MinGasPrice: minGasPrice,
|
||||
}
|
||||
}
|
||||
|
||||
@ -43,6 +52,7 @@ func DefaultParams() Params {
|
||||
ElasticityMultiplier: params.ElasticityMultiplier,
|
||||
BaseFee: sdk.NewIntFromUint64(params.InitialBaseFee),
|
||||
EnableHeight: 0,
|
||||
MinGasPrice: sdk.ZeroDec(),
|
||||
}
|
||||
}
|
||||
|
||||
@ -54,6 +64,7 @@ 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),
|
||||
}
|
||||
}
|
||||
|
||||
@ -71,7 +82,7 @@ func (p Params) Validate() error {
|
||||
return fmt.Errorf("enable height cannot be negative: %d", p.EnableHeight)
|
||||
}
|
||||
|
||||
return nil
|
||||
return validateMinGasPrice(p.MinGasPrice)
|
||||
}
|
||||
|
||||
func (p *Params) IsBaseFeeEnabled(height int64) bool {
|
||||
@ -132,3 +143,21 @@ 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
|
||||
}
|
||||
|
@ -1,9 +1,10 @@
|
||||
package types
|
||||
|
||||
import (
|
||||
sdk "github.com/cosmos/cosmos-sdk/types"
|
||||
"testing"
|
||||
|
||||
sdk "github.com/cosmos/cosmos-sdk/types"
|
||||
|
||||
paramtypes "github.com/cosmos/cosmos-sdk/x/params/types"
|
||||
"github.com/stretchr/testify/suite"
|
||||
)
|
||||
@ -29,7 +30,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)),
|
||||
false,
|
||||
},
|
||||
{
|
||||
@ -39,7 +40,12 @@ 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)),
|
||||
true,
|
||||
},
|
||||
{
|
||||
"invalid: min gas price negative",
|
||||
NewParams(true, 7, 3, 2000000000, int64(544435345345435345), sdk.NewDecFromInt(sdk.NewInt(-1))),
|
||||
true,
|
||||
},
|
||||
}
|
||||
@ -71,3 +77,30 @@ func (suite *ParamsTestSuite) TestParamsValidatePriv() {
|
||||
suite.Require().Error(validateEnableHeight(int64(-544435345345435345)))
|
||||
suite.Require().NoError(validateEnableHeight(int64(544435345345435345)))
|
||||
}
|
||||
|
||||
func (suite *ParamsTestSuite) TestParamsValidateMinGasPrice() {
|
||||
testCases := []struct {
|
||||
name string
|
||||
value interface{}
|
||||
expError bool
|
||||
}{
|
||||
{"default", DefaultParams().MinGasPrice, false},
|
||||
{"valid", sdk.NewDecFromInt(sdk.NewInt(1)), false},
|
||||
{"invalid - wrong type - bool", false, true},
|
||||
{"invalid - wrong type - string", "", true},
|
||||
{"invalid - wrong type - int64", int64(123), true},
|
||||
{"invalid - wrong type - sdk.Int", sdk.NewInt(1), true},
|
||||
{"invalid - is nil", nil, true},
|
||||
{"invalid - is negative", sdk.NewDecFromInt(sdk.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)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user