laconicd-deprecated/x/evm/keeper/utils_test.go
yihuang e1560849dd
feat(ante, evm): set priority for eth transactions (#1214)
* 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>
2022-08-05 15:00:31 +02:00

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: &ethtypes.AccessList{},
expectPass: true,
},
{
name: "Equal balance",
to: suite.address.String(),
gasLimit: 99,
gasPrice: &oneInt,
cost: &oneInt,
from: suite.address.String(),
accessList: &ethtypes.AccessList{},
expectPass: true,
},
{
name: "negative cost",
to: suite.address.String(),
gasLimit: 1,
gasPrice: &oneInt,
cost: &negInt,
from: suite.address.String(),
accessList: &ethtypes.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: &ethtypes.AccessList{},
expectPass: false,
},
{
name: "Higher gas price, enough balance",
to: suite.address.String(),
gasLimit: 10,
gasPrice: &fiveInt,
cost: &oneInt,
from: suite.address.String(),
accessList: &ethtypes.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: &ethtypes.AccessList{},
expectPass: false,
},
{
name: "Higher cost, enough balance",
to: suite.address.String(),
gasLimit: 10,
gasPrice: &fiveInt,
cost: &fiftyInt,
from: suite.address.String(),
accessList: &ethtypes.AccessList{},
expectPass: true,
},
{
name: "Higher cost, not enough balance",
to: suite.address.String(),
gasLimit: 10,
gasPrice: &fiveInt,
cost: &hundredInt,
from: suite.address.String(),
accessList: &ethtypes.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: &ethtypes.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: &ethtypes.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: &ethtypes.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: &ethtypes.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: &ethtypes.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: &ethtypes.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: &ethtypes.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: &ethtypes.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: &ethtypes.AccessList{},
expectPass: true,
},
{
name: "Equal balance",
gasLimit: 100,
gasPrice: &oneInt,
cost: &oneInt,
accessList: &ethtypes.AccessList{},
expectPass: true,
},
{
name: "Higher gas limit, not enough balance",
gasLimit: 105,
gasPrice: &oneInt,
cost: &oneInt,
accessList: &ethtypes.AccessList{},
expectPass: false,
},
{
name: "Higher gas price, enough balance",
gasLimit: 20,
gasPrice: &fiveInt,
cost: &oneInt,
accessList: &ethtypes.AccessList{},
expectPass: true,
},
{
name: "Higher gas price, not enough balance",
gasLimit: 20,
gasPrice: &fiftyInt,
cost: &oneInt,
accessList: &ethtypes.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: &ethtypes.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: &ethtypes.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: &ethtypes.AccessList{},
expectPass: true,
enableFeemarket: true,
},
{
name: "effectiveTip equal to gasTipCap",
gasLimit: 100,
gasFeeCap: big.NewInt(ethparams.InitialBaseFee + 2),
cost: &oneInt,
accessList: &ethtypes.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: &ethtypes.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
}