e1560849dd
* Set priority for eth transactions Set the tx priority to the lowest priority in the messages. fix unit tests code cleanup and spec update spec fix go lint add priority integration test add python linter job add access list tx type fix gas limit remove ledger tag, so no need to replace hid dependency fix earlier check ibc-go v5.0.0-beta1 * fix pruned node integration test * Update x/feemarket/spec/09_antehandlers.md Co-authored-by: Federico Kunze Küllmer <31522760+fedekunze@users.noreply.github.com>
445 lines
12 KiB
Go
445 lines
12 KiB
Go
package keeper_test
|
|
|
|
import (
|
|
"math/big"
|
|
|
|
sdkmath "cosmossdk.io/math"
|
|
sdk "github.com/cosmos/cosmos-sdk/types"
|
|
"github.com/ethereum/go-ethereum/common"
|
|
ethtypes "github.com/ethereum/go-ethereum/core/types"
|
|
ethparams "github.com/ethereum/go-ethereum/params"
|
|
evmkeeper "github.com/evmos/ethermint/x/evm/keeper"
|
|
evmtypes "github.com/evmos/ethermint/x/evm/types"
|
|
)
|
|
|
|
func (suite *KeeperTestSuite) TestCheckSenderBalance() {
|
|
hundredInt := sdkmath.NewInt(100)
|
|
zeroInt := sdk.ZeroInt()
|
|
oneInt := sdk.OneInt()
|
|
fiveInt := sdkmath.NewInt(5)
|
|
fiftyInt := sdkmath.NewInt(50)
|
|
negInt := sdkmath.NewInt(-10)
|
|
|
|
testCases := []struct {
|
|
name string
|
|
to string
|
|
gasLimit uint64
|
|
gasPrice *sdkmath.Int
|
|
gasFeeCap *big.Int
|
|
gasTipCap *big.Int
|
|
cost *sdkmath.Int
|
|
from string
|
|
accessList *ethtypes.AccessList
|
|
expectPass bool
|
|
enableFeemarket bool
|
|
}{
|
|
{
|
|
name: "Enough balance",
|
|
to: suite.address.String(),
|
|
gasLimit: 10,
|
|
gasPrice: &oneInt,
|
|
cost: &oneInt,
|
|
from: suite.address.String(),
|
|
accessList: ðtypes.AccessList{},
|
|
expectPass: true,
|
|
},
|
|
{
|
|
name: "Equal balance",
|
|
to: suite.address.String(),
|
|
gasLimit: 99,
|
|
gasPrice: &oneInt,
|
|
cost: &oneInt,
|
|
from: suite.address.String(),
|
|
accessList: ðtypes.AccessList{},
|
|
expectPass: true,
|
|
},
|
|
{
|
|
name: "negative cost",
|
|
to: suite.address.String(),
|
|
gasLimit: 1,
|
|
gasPrice: &oneInt,
|
|
cost: &negInt,
|
|
from: suite.address.String(),
|
|
accessList: ðtypes.AccessList{},
|
|
expectPass: false,
|
|
},
|
|
{
|
|
name: "Higher gas limit, not enough balance",
|
|
to: suite.address.String(),
|
|
gasLimit: 100,
|
|
gasPrice: &oneInt,
|
|
cost: &oneInt,
|
|
from: suite.address.String(),
|
|
accessList: ðtypes.AccessList{},
|
|
expectPass: false,
|
|
},
|
|
{
|
|
name: "Higher gas price, enough balance",
|
|
to: suite.address.String(),
|
|
gasLimit: 10,
|
|
gasPrice: &fiveInt,
|
|
cost: &oneInt,
|
|
from: suite.address.String(),
|
|
accessList: ðtypes.AccessList{},
|
|
expectPass: true,
|
|
},
|
|
{
|
|
name: "Higher gas price, not enough balance",
|
|
to: suite.address.String(),
|
|
gasLimit: 20,
|
|
gasPrice: &fiveInt,
|
|
cost: &oneInt,
|
|
from: suite.address.String(),
|
|
accessList: ðtypes.AccessList{},
|
|
expectPass: false,
|
|
},
|
|
{
|
|
name: "Higher cost, enough balance",
|
|
to: suite.address.String(),
|
|
gasLimit: 10,
|
|
gasPrice: &fiveInt,
|
|
cost: &fiftyInt,
|
|
from: suite.address.String(),
|
|
accessList: ðtypes.AccessList{},
|
|
expectPass: true,
|
|
},
|
|
{
|
|
name: "Higher cost, not enough balance",
|
|
to: suite.address.String(),
|
|
gasLimit: 10,
|
|
gasPrice: &fiveInt,
|
|
cost: &hundredInt,
|
|
from: suite.address.String(),
|
|
accessList: ðtypes.AccessList{},
|
|
expectPass: false,
|
|
},
|
|
{
|
|
name: "Enough balance w/ enableFeemarket",
|
|
to: suite.address.String(),
|
|
gasLimit: 10,
|
|
gasFeeCap: big.NewInt(1),
|
|
cost: &oneInt,
|
|
from: suite.address.String(),
|
|
accessList: ðtypes.AccessList{},
|
|
expectPass: true,
|
|
enableFeemarket: true,
|
|
},
|
|
{
|
|
name: "Equal balance w/ enableFeemarket",
|
|
to: suite.address.String(),
|
|
gasLimit: 99,
|
|
gasFeeCap: big.NewInt(1),
|
|
cost: &oneInt,
|
|
from: suite.address.String(),
|
|
accessList: ðtypes.AccessList{},
|
|
expectPass: true,
|
|
enableFeemarket: true,
|
|
},
|
|
{
|
|
name: "negative cost w/ enableFeemarket",
|
|
to: suite.address.String(),
|
|
gasLimit: 1,
|
|
gasFeeCap: big.NewInt(1),
|
|
cost: &negInt,
|
|
from: suite.address.String(),
|
|
accessList: ðtypes.AccessList{},
|
|
expectPass: false,
|
|
enableFeemarket: true,
|
|
},
|
|
{
|
|
name: "Higher gas limit, not enough balance w/ enableFeemarket",
|
|
to: suite.address.String(),
|
|
gasLimit: 100,
|
|
gasFeeCap: big.NewInt(1),
|
|
cost: &oneInt,
|
|
from: suite.address.String(),
|
|
accessList: ðtypes.AccessList{},
|
|
expectPass: false,
|
|
enableFeemarket: true,
|
|
},
|
|
{
|
|
name: "Higher gas price, enough balance w/ enableFeemarket",
|
|
to: suite.address.String(),
|
|
gasLimit: 10,
|
|
gasFeeCap: big.NewInt(5),
|
|
cost: &oneInt,
|
|
from: suite.address.String(),
|
|
accessList: ðtypes.AccessList{},
|
|
expectPass: true,
|
|
enableFeemarket: true,
|
|
},
|
|
{
|
|
name: "Higher gas price, not enough balance w/ enableFeemarket",
|
|
to: suite.address.String(),
|
|
gasLimit: 20,
|
|
gasFeeCap: big.NewInt(5),
|
|
cost: &oneInt,
|
|
from: suite.address.String(),
|
|
accessList: ðtypes.AccessList{},
|
|
expectPass: false,
|
|
enableFeemarket: true,
|
|
},
|
|
{
|
|
name: "Higher cost, enough balance w/ enableFeemarket",
|
|
to: suite.address.String(),
|
|
gasLimit: 10,
|
|
gasFeeCap: big.NewInt(5),
|
|
cost: &fiftyInt,
|
|
from: suite.address.String(),
|
|
accessList: ðtypes.AccessList{},
|
|
expectPass: true,
|
|
enableFeemarket: true,
|
|
},
|
|
{
|
|
name: "Higher cost, not enough balance w/ enableFeemarket",
|
|
to: suite.address.String(),
|
|
gasLimit: 10,
|
|
gasFeeCap: big.NewInt(5),
|
|
cost: &hundredInt,
|
|
from: suite.address.String(),
|
|
accessList: ðtypes.AccessList{},
|
|
expectPass: false,
|
|
enableFeemarket: true,
|
|
},
|
|
}
|
|
|
|
vmdb := suite.StateDB()
|
|
vmdb.AddBalance(suite.address, hundredInt.BigInt())
|
|
balance := vmdb.GetBalance(suite.address)
|
|
suite.Require().Equal(balance, hundredInt.BigInt())
|
|
vmdb.Commit()
|
|
|
|
for i, tc := range testCases {
|
|
suite.Run(tc.name, func() {
|
|
to := common.HexToAddress(tc.from)
|
|
|
|
var amount, gasPrice, gasFeeCap, gasTipCap *big.Int
|
|
if tc.cost != nil {
|
|
amount = tc.cost.BigInt()
|
|
}
|
|
|
|
if tc.enableFeemarket {
|
|
gasFeeCap = tc.gasFeeCap
|
|
if tc.gasTipCap == nil {
|
|
gasTipCap = oneInt.BigInt()
|
|
} else {
|
|
gasTipCap = tc.gasTipCap
|
|
}
|
|
} else {
|
|
if tc.gasPrice != nil {
|
|
gasPrice = tc.gasPrice.BigInt()
|
|
}
|
|
}
|
|
|
|
tx := evmtypes.NewTx(zeroInt.BigInt(), 1, &to, amount, tc.gasLimit, gasPrice, gasFeeCap, gasTipCap, nil, tc.accessList)
|
|
tx.From = tc.from
|
|
|
|
txData, _ := evmtypes.UnpackTxData(tx.Data)
|
|
|
|
acct := suite.app.EvmKeeper.GetAccountOrEmpty(suite.ctx, suite.address)
|
|
err := evmkeeper.CheckSenderBalance(
|
|
sdkmath.NewIntFromBigInt(acct.Balance),
|
|
txData,
|
|
)
|
|
|
|
if tc.expectPass {
|
|
suite.Require().NoError(err, "valid test %d failed", i)
|
|
} else {
|
|
suite.Require().Error(err, "invalid test %d passed", i)
|
|
}
|
|
})
|
|
}
|
|
}
|
|
|
|
func (suite *KeeperTestSuite) TestDeductTxCostsFromUserBalance() {
|
|
hundredInt := sdkmath.NewInt(100)
|
|
zeroInt := sdk.ZeroInt()
|
|
oneInt := sdkmath.NewInt(1)
|
|
fiveInt := sdkmath.NewInt(5)
|
|
fiftyInt := sdkmath.NewInt(50)
|
|
|
|
// should be enough to cover all test cases
|
|
initBalance := sdkmath.NewInt((ethparams.InitialBaseFee + 10) * 105)
|
|
|
|
testCases := []struct {
|
|
name string
|
|
gasLimit uint64
|
|
gasPrice *sdkmath.Int
|
|
gasFeeCap *big.Int
|
|
gasTipCap *big.Int
|
|
cost *sdkmath.Int
|
|
accessList *ethtypes.AccessList
|
|
expectPass bool
|
|
enableFeemarket bool
|
|
}{
|
|
{
|
|
name: "Enough balance",
|
|
gasLimit: 10,
|
|
gasPrice: &oneInt,
|
|
cost: &oneInt,
|
|
accessList: ðtypes.AccessList{},
|
|
expectPass: true,
|
|
},
|
|
{
|
|
name: "Equal balance",
|
|
gasLimit: 100,
|
|
gasPrice: &oneInt,
|
|
cost: &oneInt,
|
|
accessList: ðtypes.AccessList{},
|
|
expectPass: true,
|
|
},
|
|
{
|
|
name: "Higher gas limit, not enough balance",
|
|
gasLimit: 105,
|
|
gasPrice: &oneInt,
|
|
cost: &oneInt,
|
|
accessList: ðtypes.AccessList{},
|
|
expectPass: false,
|
|
},
|
|
{
|
|
name: "Higher gas price, enough balance",
|
|
gasLimit: 20,
|
|
gasPrice: &fiveInt,
|
|
cost: &oneInt,
|
|
accessList: ðtypes.AccessList{},
|
|
expectPass: true,
|
|
},
|
|
{
|
|
name: "Higher gas price, not enough balance",
|
|
gasLimit: 20,
|
|
gasPrice: &fiftyInt,
|
|
cost: &oneInt,
|
|
accessList: ðtypes.AccessList{},
|
|
expectPass: false,
|
|
},
|
|
// This case is expected to be true because the fees can be deducted, but the tx
|
|
// execution is going to fail because there is no more balance to pay the cost
|
|
{
|
|
name: "Higher cost, enough balance",
|
|
gasLimit: 100,
|
|
gasPrice: &oneInt,
|
|
cost: &fiftyInt,
|
|
accessList: ðtypes.AccessList{},
|
|
expectPass: true,
|
|
},
|
|
// testcases with enableFeemarket enabled.
|
|
{
|
|
name: "Invalid gasFeeCap w/ enableFeemarket",
|
|
gasLimit: 10,
|
|
gasFeeCap: big.NewInt(1),
|
|
gasTipCap: big.NewInt(1),
|
|
cost: &oneInt,
|
|
accessList: ðtypes.AccessList{},
|
|
expectPass: false,
|
|
enableFeemarket: true,
|
|
},
|
|
{
|
|
name: "empty tip fee is valid to deduct",
|
|
gasLimit: 10,
|
|
gasFeeCap: big.NewInt(ethparams.InitialBaseFee),
|
|
gasTipCap: big.NewInt(1),
|
|
cost: &oneInt,
|
|
accessList: ðtypes.AccessList{},
|
|
expectPass: true,
|
|
enableFeemarket: true,
|
|
},
|
|
{
|
|
name: "effectiveTip equal to gasTipCap",
|
|
gasLimit: 100,
|
|
gasFeeCap: big.NewInt(ethparams.InitialBaseFee + 2),
|
|
cost: &oneInt,
|
|
accessList: ðtypes.AccessList{},
|
|
expectPass: true,
|
|
enableFeemarket: true,
|
|
},
|
|
{
|
|
name: "effectiveTip equal to (gasFeeCap - baseFee)",
|
|
gasLimit: 105,
|
|
gasFeeCap: big.NewInt(ethparams.InitialBaseFee + 1),
|
|
gasTipCap: big.NewInt(2),
|
|
cost: &oneInt,
|
|
accessList: ðtypes.AccessList{},
|
|
expectPass: true,
|
|
enableFeemarket: true,
|
|
},
|
|
}
|
|
|
|
for i, tc := range testCases {
|
|
suite.Run(tc.name, func() {
|
|
suite.enableFeemarket = tc.enableFeemarket
|
|
suite.SetupTest()
|
|
vmdb := suite.StateDB()
|
|
|
|
var amount, gasPrice, gasFeeCap, gasTipCap *big.Int
|
|
if tc.cost != nil {
|
|
amount = tc.cost.BigInt()
|
|
}
|
|
|
|
if suite.enableFeemarket {
|
|
if tc.gasFeeCap != nil {
|
|
gasFeeCap = tc.gasFeeCap
|
|
}
|
|
if tc.gasTipCap == nil {
|
|
gasTipCap = oneInt.BigInt()
|
|
} else {
|
|
gasTipCap = tc.gasTipCap
|
|
}
|
|
vmdb.AddBalance(suite.address, initBalance.BigInt())
|
|
balance := vmdb.GetBalance(suite.address)
|
|
suite.Require().Equal(balance, initBalance.BigInt())
|
|
} else {
|
|
if tc.gasPrice != nil {
|
|
gasPrice = tc.gasPrice.BigInt()
|
|
}
|
|
|
|
vmdb.AddBalance(suite.address, hundredInt.BigInt())
|
|
balance := vmdb.GetBalance(suite.address)
|
|
suite.Require().Equal(balance, hundredInt.BigInt())
|
|
}
|
|
vmdb.Commit()
|
|
|
|
tx := evmtypes.NewTx(zeroInt.BigInt(), 1, &suite.address, amount, tc.gasLimit, gasPrice, gasFeeCap, gasTipCap, nil, tc.accessList)
|
|
tx.From = suite.address.String()
|
|
|
|
txData, _ := evmtypes.UnpackTxData(tx.Data)
|
|
|
|
fees, priority, err := suite.app.EvmKeeper.DeductTxCostsFromUserBalance(
|
|
suite.ctx,
|
|
*tx,
|
|
txData,
|
|
evmtypes.DefaultEVMDenom,
|
|
false,
|
|
false,
|
|
suite.enableFeemarket, // london
|
|
)
|
|
|
|
if tc.expectPass {
|
|
suite.Require().NoError(err, "valid test %d failed", i)
|
|
if tc.enableFeemarket {
|
|
baseFee := suite.app.FeeMarketKeeper.GetBaseFee(suite.ctx)
|
|
suite.Require().Equal(
|
|
fees,
|
|
sdk.NewCoins(
|
|
sdk.NewCoin(evmtypes.DefaultEVMDenom, sdkmath.NewIntFromBigInt(txData.EffectiveFee(baseFee))),
|
|
),
|
|
"valid test %d failed, fee value is wrong ", i,
|
|
)
|
|
suite.Require().Equal(int64(0), priority)
|
|
} else {
|
|
suite.Require().Equal(
|
|
fees,
|
|
sdk.NewCoins(
|
|
sdk.NewCoin(evmtypes.DefaultEVMDenom, tc.gasPrice.Mul(sdkmath.NewIntFromUint64(tc.gasLimit))),
|
|
),
|
|
"valid test %d failed, fee value is wrong ", i,
|
|
)
|
|
}
|
|
} else {
|
|
suite.Require().Error(err, "invalid test %d passed", i)
|
|
suite.Require().Nil(fees, "invalid test %d passed. fees value must be nil", i)
|
|
}
|
|
})
|
|
}
|
|
suite.enableFeemarket = false // reset flag
|
|
}
|