tests: DynamicFeeTx (#649)

* test DynamicFeeTx against state_transition_benchmark_test

* add feemarketGenesis in the app setup param

* add dynamicTxFee flag to KeeperTestSuite

* add feemarketGenesis.BaseFee setup

* update TestAddLog

* fix gasFeeCap assignment in newMsgEthereumTx

* modify keeperTestSuite helper functions to support dynamicTxFee

* update test cases in grpc_query_test w/ dynamicTxFee

* update the evm keeper utils tests

* add dynamic tx fee in the ante tests

* remove duplicate type define

* fix error return type

* update changelog

Co-authored-by: Federico Kunze Küllmer <31522760+fedekunze@users.noreply.github.com>
This commit is contained in:
JayT106
2021-10-19 08:49:29 +00:00
committed by GitHub
co-authored by Federico Kunze Küllmer
parent 2f531af3f2
commit 1076307e6b
12 changed files with 780 additions and 82 deletions
+12 -1
View File
@@ -13,6 +13,7 @@ import (
"github.com/cosmos/cosmos-sdk/simapp"
authtypes "github.com/cosmos/cosmos-sdk/x/auth/types"
banktypes "github.com/cosmos/cosmos-sdk/x/bank/types"
feemarkettypes "github.com/tharsis/ethermint/x/feemarket/types"
stakingtypes "github.com/cosmos/cosmos-sdk/x/staking/types"
"github.com/ethereum/go-ethereum/common"
@@ -53,6 +54,8 @@ type EvmTestSuite struct {
ethSigner ethtypes.Signer
from common.Address
to sdk.AccAddress
dynamicTxFee bool
}
/// DoSetupTest setup test environment, it uses`require.TestingT` to support both `testing.T` and `testing.B`.
@@ -70,7 +73,15 @@ func (suite *EvmTestSuite) DoSetupTest(t require.TestingT) {
require.NoError(t, err)
consAddress := sdk.ConsAddress(priv.PubKey().Address())
suite.app = app.Setup(checkTx)
if suite.dynamicTxFee {
feemarketGenesis := feemarkettypes.DefaultGenesisState()
feemarketGenesis.Params.EnableHeight = 1
feemarketGenesis.Params.NoBaseFee = false
suite.app = app.Setup(checkTx, feemarketGenesis)
} else {
suite.app = app.Setup(checkTx, nil)
}
coins := sdk.NewCoins(sdk.NewCoin(types.DefaultEVMDenom, sdk.NewInt(100000000000000)))
genesisState := app.ModuleBasics.DefaultGenesis(suite.app.AppCodec())
b32address := sdk.MustBech32ifyAddressBytes(sdk.GetConfig().GetBech32AccountAddrPrefix(), priv.PubKey().Address().Bytes())
+71 -11
View File
@@ -485,32 +485,33 @@ func (suite *KeeperTestSuite) TestEstimateGas() {
gasCap uint64
)
testCases := []struct {
msg string
malleate func()
expPass bool
expGas uint64
msg string
malleate func()
expPass bool
expGas uint64
dynamicTxFee bool
}{
// should success, because transfer value is zero
{"default args", func() {
args = types.TransactionArgs{To: &common.Address{}}
}, true, 21000},
}, true, 21000, false},
// should fail, because the default From address(zero address) don't have fund
{"not enough balance", func() {
args = types.TransactionArgs{To: &common.Address{}, Value: (*hexutil.Big)(big.NewInt(100))}
}, false, 0},
}, false, 0, false},
// should success, enough balance now
{"enough balance", func() {
args = types.TransactionArgs{To: &common.Address{}, From: &suite.address, Value: (*hexutil.Big)(big.NewInt(100))}
}, false, 0},
}, false, 0, false},
// should success, because gas limit lower than 21000 is ignored
{"gas exceed allowance", func() {
args = types.TransactionArgs{To: &common.Address{}, Gas: &gasHelper}
}, true, 21000},
}, true, 21000, false},
// should fail, invalid gas cap
{"gas exceed global allowance", func() {
args = types.TransactionArgs{To: &common.Address{}}
gasCap = 20000
}, false, 0},
}, false, 0, false},
// estimate gas of an erc20 contract deployment, the exact gas number is checked with geth
{"contract deployment", func() {
ctorArgs, err := ContractABI.Pack("", &suite.address, sdk.NewIntWithDecimal(1000, 18).BigInt())
@@ -520,7 +521,7 @@ func (suite *KeeperTestSuite) TestEstimateGas() {
From: &suite.address,
Data: (*hexutil.Bytes)(&data),
}
}, true, 1186778},
}, true, 1186778, false},
// estimate gas of an erc20 transfer, the exact gas number is checked with geth
{"erc20 transfer", func() {
contractAddr := suite.DeployTestContract(suite.T(), suite.address, sdk.NewIntWithDecimal(1000, 18).BigInt())
@@ -528,11 +529,46 @@ func (suite *KeeperTestSuite) TestEstimateGas() {
transferData, err := ContractABI.Pack("transfer", common.HexToAddress("0x378c50D9264C63F3F92B806d4ee56E9D86FfB3Ec"), big.NewInt(1000))
suite.Require().NoError(err)
args = types.TransactionArgs{To: &contractAddr, From: &suite.address, Data: (*hexutil.Bytes)(&transferData)}
}, true, 51880},
}, true, 51880, false},
// repeated tests with dynamicTxFee
{"default args w/ dynamicTxFee", func() {
args = types.TransactionArgs{To: &common.Address{}}
}, true, 21000, true},
{"not enough balance w/ dynamicTxFee", func() {
args = types.TransactionArgs{To: &common.Address{}, Value: (*hexutil.Big)(big.NewInt(100))}
}, false, 0, true},
{"enough balance w/ dynamicTxFee", func() {
args = types.TransactionArgs{To: &common.Address{}, From: &suite.address, Value: (*hexutil.Big)(big.NewInt(100))}
}, false, 0, true},
{"gas exceed allowance w/ dynamicTxFee", func() {
args = types.TransactionArgs{To: &common.Address{}, Gas: &gasHelper}
}, true, 21000, true},
{"gas exceed global allowance w/ dynamicTxFee", func() {
args = types.TransactionArgs{To: &common.Address{}}
gasCap = 20000
}, false, 0, true},
{"contract deployment w/ dynamicTxFee", func() {
ctorArgs, err := ContractABI.Pack("", &suite.address, sdk.NewIntWithDecimal(1000, 18).BigInt())
suite.Require().NoError(err)
data := append(ContractBin, ctorArgs...)
args = types.TransactionArgs{
From: &suite.address,
Data: (*hexutil.Bytes)(&data),
}
}, true, 1186778, true},
{"erc20 transfer w/ dynamicTxFee", func() {
contractAddr := suite.DeployTestContract(suite.T(), suite.address, sdk.NewIntWithDecimal(1000, 18).BigInt())
suite.Commit()
transferData, err := ContractABI.Pack("transfer", common.HexToAddress("0x378c50D9264C63F3F92B806d4ee56E9D86FfB3Ec"), big.NewInt(1000))
suite.Require().NoError(err)
args = types.TransactionArgs{To: &contractAddr, From: &suite.address, Data: (*hexutil.Bytes)(&transferData)}
}, true, 51880, true},
}
for _, tc := range testCases {
suite.Run(fmt.Sprintf("Case %s", tc.msg), func() {
suite.dynamicTxFee = tc.dynamicTxFee
suite.SetupTest()
gasCap = 25_000_000
tc.malleate()
@@ -553,6 +589,7 @@ func (suite *KeeperTestSuite) TestEstimateGas() {
}
})
}
suite.dynamicTxFee = false // reset flag
}
func (suite *KeeperTestSuite) TestTraceTx() {
@@ -568,6 +605,7 @@ func (suite *KeeperTestSuite) TestTraceTx() {
malleate func()
expPass bool
traceResponse []byte
dynamicTxFee bool
}{
{
msg: "default trace",
@@ -586,10 +624,30 @@ func (suite *KeeperTestSuite) TestTraceTx() {
expPass: true,
traceResponse: []byte{0x5b, 0x5d},
},
{
msg: "default trace with dynamicTxFee",
malleate: func() {
traceConfig = nil
},
expPass: true,
traceResponse: []byte{0x7b, 0x22, 0x67, 0x61, 0x73, 0x22, 0x3a, 0x33, 0x34, 0x38, 0x32, 0x38, 0x2c, 0x22, 0x66, 0x61, 0x69, 0x6c, 0x65, 0x64, 0x22, 0x3a, 0x66, 0x61, 0x6c, 0x73, 0x65, 0x2c, 0x22, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x22, 0x3a, 0x22, 0x22, 0x2c, 0x22, 0x73, 0x74, 0x72, 0x75, 0x63, 0x74, 0x4c, 0x6f, 0x67, 0x73, 0x22, 0x3a, 0x5b, 0x5d, 0x7d},
dynamicTxFee: true,
}, {
msg: "javascript tracer with dynamicTxFee",
malleate: func() {
traceConfig = &types.TraceConfig{
Tracer: "{data: [], fault: function(log) {}, step: function(log) { if(log.op.toString() == \"CALL\") this.data.push(log.stack.peek(0)); }, result: function() { return this.data; }}",
}
},
expPass: true,
traceResponse: []byte{0x5b, 0x5d},
dynamicTxFee: true,
},
}
for _, tc := range testCases {
suite.Run(fmt.Sprintf("Case %s", tc.msg), func() {
suite.dynamicTxFee = tc.dynamicTxFee
suite.SetupTest()
// Deploy contract
contractAddr := suite.DeployTestContract(suite.T(), suite.address, sdk.NewIntWithDecimal(1000, 18).BigInt())
@@ -614,4 +672,6 @@ func (suite *KeeperTestSuite) TestTraceTx() {
}
})
}
suite.dynamicTxFee = false // reset flag
}
+70 -22
View File
@@ -17,6 +17,7 @@ import (
sdk "github.com/cosmos/cosmos-sdk/types"
authtypes "github.com/cosmos/cosmos-sdk/x/auth/types"
stakingtypes "github.com/cosmos/cosmos-sdk/x/staking/types"
feemarkettypes "github.com/tharsis/ethermint/x/feemarket/types"
"github.com/tharsis/ethermint/app"
"github.com/tharsis/ethermint/crypto/ethsecp256k1"
@@ -79,6 +80,8 @@ type KeeperTestSuite struct {
appCodec codec.Codec
signer keyring.Signer
dynamicTxFee bool
}
/// DoSetupTest setup test environment, it uses`require.TestingT` to support both `testing.T` and `testing.B`.
@@ -96,7 +99,17 @@ func (suite *KeeperTestSuite) DoSetupTest(t require.TestingT) {
require.NoError(t, err)
suite.consAddress = sdk.ConsAddress(priv.PubKey().Address())
suite.app = app.Setup(checkTx)
if suite.dynamicTxFee {
// setup feemarketGenesis params
feemarketGenesis := feemarkettypes.DefaultGenesisState()
feemarketGenesis.Params.EnableHeight = 1
feemarketGenesis.Params.NoBaseFee = false
feemarketGenesis.BaseFee = sdk.NewInt(feemarketGenesis.Params.InitialBaseFee)
suite.app = app.Setup(checkTx, feemarketGenesis)
} else {
suite.app = app.Setup(checkTx, nil)
}
suite.ctx = suite.app.BaseApp.NewContext(checkTx, tmproto.Header{
Height: 1,
ChainID: "ethermint_9000-1",
@@ -197,16 +210,33 @@ func (suite *KeeperTestSuite) DeployTestContract(t require.TestingT, owner commo
require.NoError(t, err)
nonce := suite.app.EvmKeeper.GetNonce(suite.address)
erc20DeployTx := types.NewTxContract(
chainID,
nonce,
nil, // amount
res.Gas, // gasLimit
nil, // gasPrice
nil, nil,
data, // input
nil, // accesses
)
var erc20DeployTx *types.MsgEthereumTx
if suite.dynamicTxFee {
erc20DeployTx = types.NewTxContract(
chainID,
nonce,
nil, // amount
res.Gas, // gasLimit
nil, // gasPrice
suite.app.FeeMarketKeeper.GetBaseFee(suite.ctx),
big.NewInt(1),
data, // input
&ethtypes.AccessList{}, // accesses
)
} else {
erc20DeployTx = types.NewTxContract(
chainID,
nonce,
nil, // amount
res.Gas, // gasLimit
nil, // gasPrice
nil, nil,
data, // input
nil, // accesses
)
}
erc20DeployTx.From = suite.address.Hex()
err = erc20DeployTx.Sign(ethtypes.LatestSignerForChainID(chainID), suite.signer)
require.NoError(t, err)
@@ -231,17 +261,35 @@ func (suite *KeeperTestSuite) TransferERC20Token(t require.TestingT, contractAdd
require.NoError(t, err)
nonce := suite.app.EvmKeeper.GetNonce(suite.address)
ercTransferTx := types.NewTx(
chainID,
nonce,
&contractAddr,
nil,
res.Gas,
nil,
nil, nil,
transferData,
nil,
)
var ercTransferTx *types.MsgEthereumTx
if suite.dynamicTxFee {
ercTransferTx = types.NewTx(
chainID,
nonce,
&contractAddr,
nil,
res.Gas,
nil,
suite.app.FeeMarketKeeper.GetBaseFee(suite.ctx),
big.NewInt(1),
transferData,
&ethtypes.AccessList{}, // accesses
)
} else {
ercTransferTx = types.NewTx(
chainID,
nonce,
&contractAddr,
nil,
res.Gas,
nil,
nil, nil,
transferData,
nil,
)
}
ercTransferTx.From = suite.address.Hex()
err = ercTransferTx.Sign(ethtypes.LatestSignerForChainID(chainID), suite.signer)
require.NoError(t, err)
@@ -31,6 +31,15 @@ var templateLegacyTx = &ethtypes.LegacyTx{
Data: []byte{},
}
var templateDynamicFeeTx = &ethtypes.DynamicFeeTx{
GasFeeCap: big.NewInt(10),
GasTipCap: big.NewInt(2),
Gas: 21000,
To: &common.Address{},
Value: big.NewInt(0),
Data: []byte{},
}
func newSignedEthTx(
txData ethtypes.TxData,
nonce uint64,
@@ -46,6 +55,9 @@ func newSignedEthTx(
case *ethtypes.LegacyTx:
txData.Nonce = nonce
ethTx = ethtypes.NewTx(txData)
case *ethtypes.DynamicFeeTx:
txData.Nonce = nonce
ethTx = ethtypes.NewTx(txData)
default:
return nil, errors.New("unknown transaction type!")
}
@@ -70,7 +82,7 @@ func newNativeMessage(
cfg *params.ChainConfig,
krSigner keyring.Signer,
ethSigner ethtypes.Signer,
isLegacy bool,
txType byte,
) (core.Message, error) {
msgSigner := ethtypes.MakeSigner(cfg, big.NewInt(blockHeight))
@@ -78,12 +90,20 @@ func newNativeMessage(
ethTx *ethtypes.Transaction
baseFee *big.Int
)
if isLegacy {
switch txType {
case ethtypes.LegacyTxType:
templateLegacyTx.Nonce = nonce
ethTx = ethtypes.NewTx(templateLegacyTx)
} else {
case ethtypes.AccessListTxType:
templateAccessListTx.Nonce = nonce
ethTx = ethtypes.NewTx(templateAccessListTx)
case ethtypes.DynamicFeeTxType:
templateDynamicFeeTx.Nonce = nonce
ethTx = ethtypes.NewTx(templateDynamicFeeTx)
baseFee = big.NewInt(3)
default:
return nil, errors.New("unsupport tx type")
}
msg := &evmtypes.MsgEthereumTx{}
@@ -94,7 +114,7 @@ func newNativeMessage(
return nil, err
}
m, err := msg.AsMessage(msgSigner, baseFee) // TODO: add DynamicFeeTx
m, err := msg.AsMessage(msgSigner, baseFee)
if err != nil {
return nil, err
}
@@ -156,6 +176,33 @@ func BenchmarkApplyTransactionWithLegacyTx(b *testing.B) {
}
}
func BenchmarkApplyTransactionWithDynamicFeeTx(b *testing.B) {
suite := KeeperTestSuite{dynamicTxFee: true}
suite.DoSetupTest(b)
ethSigner := ethtypes.LatestSignerForChainID(suite.app.EvmKeeper.ChainID())
b.ResetTimer()
b.ReportAllocs()
for i := 0; i < b.N; i++ {
b.StopTimer()
tx, err := newSignedEthTx(templateDynamicFeeTx,
suite.app.EvmKeeper.GetNonce(suite.address),
sdk.AccAddress(suite.address.Bytes()),
suite.signer,
ethSigner,
)
require.NoError(b, err)
b.StartTimer()
resp, err := suite.app.EvmKeeper.ApplyTransaction(tx)
b.StopTimer()
require.NoError(b, err)
require.False(b, resp.Failed())
}
}
func BenchmarkApplyNativeMessage(b *testing.B) {
suite := KeeperTestSuite{}
suite.DoSetupTest(b)
@@ -176,7 +223,7 @@ func BenchmarkApplyNativeMessage(b *testing.B) {
ethCfg,
suite.signer,
signer,
false,
ethtypes.AccessListTxType,
)
require.NoError(b, err)
@@ -209,7 +256,40 @@ func BenchmarkApplyNativeMessageWithLegacyTx(b *testing.B) {
ethCfg,
suite.signer,
signer,
true,
ethtypes.LegacyTxType,
)
require.NoError(b, err)
b.StartTimer()
resp, err := suite.app.EvmKeeper.ApplyNativeMessage(m)
b.StopTimer()
require.NoError(b, err)
require.False(b, resp.Failed())
}
}
func BenchmarkApplyNativeMessageWithDynamicFeeTx(b *testing.B) {
suite := KeeperTestSuite{dynamicTxFee: true}
suite.DoSetupTest(b)
params := suite.app.EvmKeeper.GetParams(suite.ctx)
ethCfg := params.ChainConfig.EthereumConfig(suite.app.EvmKeeper.ChainID())
signer := ethtypes.LatestSignerForChainID(suite.app.EvmKeeper.ChainID())
b.ResetTimer()
b.ReportAllocs()
for i := 0; i < b.N; i++ {
b.StopTimer()
m, err := newNativeMessage(
suite.app.EvmKeeper.GetNonce(suite.address),
suite.ctx.BlockHeight(),
suite.address,
ethCfg,
suite.signer,
signer,
ethtypes.DynamicFeeTxType,
)
require.NoError(b, err)
+46
View File
@@ -563,6 +563,20 @@ func (suite *KeeperTestSuite) TestAddLog() {
msg2, _ = tx2.GetMsgs()[0].(*types.MsgEthereumTx)
txHash2 := msg2.AsTransaction().Hash()
msg3 := types.NewTx(big.NewInt(1), 0, &suite.address, big.NewInt(1), 100000, nil, big.NewInt(1), big.NewInt(1), []byte("test"), nil)
msg3.From = addr.Hex()
tx3 := suite.CreateTestTx(msg3, privKey)
msg3, _ = tx3.GetMsgs()[0].(*types.MsgEthereumTx)
txHash3 := msg3.AsTransaction().Hash()
msg4 := types.NewTx(big.NewInt(1), 1, &suite.address, big.NewInt(1), 100000, nil, big.NewInt(1), big.NewInt(1), []byte("test"), nil)
msg4.From = addr.Hex()
tx4 := suite.CreateTestTx(msg4, privKey)
msg4, _ = tx4.GetMsgs()[0].(*types.MsgEthereumTx)
txHash4 := msg4.AsTransaction().Hash()
testCases := []struct {
name string
hash common.Hash
@@ -601,6 +615,38 @@ func (suite *KeeperTestSuite) TestAddLog() {
suite.app.EvmKeeper.IncreaseTxIndexTransient()
},
},
{
"dynamicfee tx hash from message",
txHash3,
&ethtypes.Log{
Address: addr,
},
&ethtypes.Log{
Address: addr,
TxHash: txHash3,
},
func() {},
},
{
"log index keep increasing in new dynamicfee tx",
txHash4,
&ethtypes.Log{
Address: addr,
},
&ethtypes.Log{
Address: addr,
TxHash: txHash4,
TxIndex: 1,
Index: 1,
},
func() {
suite.app.EvmKeeper.SetTxHashTransient(txHash)
suite.app.EvmKeeper.AddLog(&ethtypes.Log{
Address: addr,
})
suite.app.EvmKeeper.IncreaseTxIndexTransient()
},
},
}
for _, tc := range testCases {
+6 -1
View File
@@ -62,7 +62,12 @@ func (k Keeper) DeductTxCostsFromUserBalance(
if london && !feeMktParams.NoBaseFee && txData.TxType() == ethtypes.DynamicFeeTxType {
baseFee := k.feeMarketKeeper.GetBaseFee(ctx)
effectiveTip = cmath.BigMin(txData.GetGasTipCap(), new(big.Int).Sub(txData.GetGasFeeCap(), baseFee))
gasFeeGap := new(big.Int).Sub(txData.GetGasFeeCap(), baseFee)
if gasFeeGap.Sign() == -1 {
return nil, sdkerrors.Wrapf(sdkerrors.ErrInsufficientFee, "the tx gasfeecap is lower than the tx baseFee: %s (gasfeecap), %s (basefee) ", txData.GetGasFeeCap(), baseFee)
}
effectiveTip = cmath.BigMin(txData.GetGasTipCap(), gasFeeGap)
}
gasUsed := new(big.Int).SetUint64(txData.GetGas())
+212 -33
View File
@@ -5,7 +5,9 @@ import (
sdk "github.com/cosmos/cosmos-sdk/types"
"github.com/ethereum/go-ethereum/common"
cmath "github.com/ethereum/go-ethereum/common/math"
ethtypes "github.com/ethereum/go-ethereum/core/types"
ethparams "github.com/ethereum/go-ethereum/params"
evmkeeper "github.com/tharsis/ethermint/x/evm/keeper"
evmtypes "github.com/tharsis/ethermint/x/evm/types"
)
@@ -19,14 +21,17 @@ func (suite *KeeperTestSuite) TestCheckSenderBalance() {
negInt := sdk.NewInt(-10)
testCases := []struct {
name string
to string
gasLimit uint64
gasPrice *sdk.Int
cost *sdk.Int
from string
accessList *ethtypes.AccessList
expectPass bool
name string
to string
gasLimit uint64
gasPrice *sdk.Int
gasFeeCap *big.Int
gasTipCap *big.Int
cost *sdk.Int
from string
accessList *ethtypes.AccessList
expectPass bool
dynamicTxFee bool
}{
{
name: "Enough balance",
@@ -108,6 +113,94 @@ func (suite *KeeperTestSuite) TestCheckSenderBalance() {
accessList: &ethtypes.AccessList{},
expectPass: false,
},
{
name: "Enough balance w/ dynamicTxFee",
to: suite.address.String(),
gasLimit: 10,
gasFeeCap: big.NewInt(1),
cost: &oneInt,
from: suite.address.String(),
accessList: &ethtypes.AccessList{},
expectPass: true,
dynamicTxFee: true,
},
{
name: "Equal balance w/ dynamicTxFee",
to: suite.address.String(),
gasLimit: 99,
gasFeeCap: big.NewInt(1),
cost: &oneInt,
from: suite.address.String(),
accessList: &ethtypes.AccessList{},
expectPass: true,
dynamicTxFee: true,
},
{
name: "negative cost w/ dynamicTxFee",
to: suite.address.String(),
gasLimit: 1,
gasFeeCap: big.NewInt(1),
cost: &negInt,
from: suite.address.String(),
accessList: &ethtypes.AccessList{},
expectPass: false,
dynamicTxFee: true,
},
{
name: "Higher gas limit, not enough balance w/ dynamicTxFee",
to: suite.address.String(),
gasLimit: 100,
gasFeeCap: big.NewInt(1),
cost: &oneInt,
from: suite.address.String(),
accessList: &ethtypes.AccessList{},
expectPass: false,
dynamicTxFee: true,
},
{
name: "Higher gas price, enough balance w/ dynamicTxFee",
to: suite.address.String(),
gasLimit: 10,
gasFeeCap: big.NewInt(5),
cost: &oneInt,
from: suite.address.String(),
accessList: &ethtypes.AccessList{},
expectPass: true,
dynamicTxFee: true,
},
{
name: "Higher gas price, not enough balance w/ dynamicTxFee",
to: suite.address.String(),
gasLimit: 20,
gasFeeCap: big.NewInt(5),
cost: &oneInt,
from: suite.address.String(),
accessList: &ethtypes.AccessList{},
expectPass: false,
dynamicTxFee: true,
},
{
name: "Higher cost, enough balance w/ dynamicTxFee",
to: suite.address.String(),
gasLimit: 10,
gasFeeCap: big.NewInt(5),
cost: &fiftyInt,
from: suite.address.String(),
accessList: &ethtypes.AccessList{},
expectPass: true,
dynamicTxFee: true,
},
{
name: "Higher cost, not enough balance w/ dynamicTxFee",
to: suite.address.String(),
gasLimit: 10,
gasFeeCap: big.NewInt(5),
cost: &hundredInt,
from: suite.address.String(),
accessList: &ethtypes.AccessList{},
expectPass: false,
dynamicTxFee: true,
},
}
suite.app.EvmKeeper.AddBalance(suite.address, hundredInt.BigInt())
@@ -118,15 +211,25 @@ func (suite *KeeperTestSuite) TestCheckSenderBalance() {
suite.Run(tc.name, func() {
to := common.HexToAddress(tc.from)
var amount, gasPrice *big.Int
var amount, gasPrice, gasFeeCap, gasTipCap *big.Int
if tc.cost != nil {
amount = tc.cost.BigInt()
}
if tc.gasPrice != nil {
gasPrice = tc.gasPrice.BigInt()
if tc.dynamicTxFee {
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, nil, nil, nil, tc.accessList)
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)
@@ -154,14 +257,18 @@ func (suite *KeeperTestSuite) TestDeductTxCostsFromUserBalance() {
oneInt := sdk.NewInt(1)
fiveInt := sdk.NewInt(5)
fiftyInt := sdk.NewInt(50)
hundredBaseFeeInt := sdk.NewInt(ethparams.InitialBaseFee * 100)
testCases := []struct {
name string
gasLimit uint64
gasPrice *sdk.Int
cost *sdk.Int
accessList *ethtypes.AccessList
expectPass bool
name string
gasLimit uint64
gasPrice *sdk.Int
gasFeeCap *big.Int
gasTipCap *big.Int
cost *sdk.Int
accessList *ethtypes.AccessList
expectPass bool
dynamicTxFee bool
}{
{
name: "Enough balance",
@@ -213,24 +320,82 @@ func (suite *KeeperTestSuite) TestDeductTxCostsFromUserBalance() {
accessList: &ethtypes.AccessList{},
expectPass: true,
},
// testcases with dynamicTxFee enabled.
{
name: "Invalid gasFeeCap w/ dynamicTxFee",
gasLimit: 10,
gasFeeCap: big.NewInt(1),
gasTipCap: big.NewInt(1),
cost: &oneInt,
accessList: &ethtypes.AccessList{},
expectPass: false,
dynamicTxFee: true,
},
// TODO: is this case valid?
{
name: "empty fee failed to deduct",
gasLimit: 10,
gasFeeCap: big.NewInt(ethparams.InitialBaseFee),
gasTipCap: big.NewInt(1),
cost: &oneInt,
accessList: &ethtypes.AccessList{},
expectPass: false,
dynamicTxFee: true,
},
{
name: "effectiveTip equal to gasTipCap",
gasLimit: 100,
gasFeeCap: big.NewInt(ethparams.InitialBaseFee + 2),
cost: &oneInt,
accessList: &ethtypes.AccessList{},
expectPass: true,
dynamicTxFee: 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,
dynamicTxFee: true,
},
}
for i, tc := range testCases {
suite.Run(tc.name, func() {
suite.dynamicTxFee = tc.dynamicTxFee
suite.SetupTest()
suite.app.EvmKeeper.AddBalance(suite.address, hundredInt.BigInt())
balance := suite.app.EvmKeeper.GetBalance(suite.address)
suite.Require().Equal(balance, hundredInt.BigInt())
var amount, gasPrice *big.Int
var amount, gasPrice, gasFeeCap, gasTipCap *big.Int
if tc.cost != nil {
amount = tc.cost.BigInt()
}
if tc.gasPrice != nil {
gasPrice = tc.gasPrice.BigInt()
if suite.dynamicTxFee {
if tc.gasFeeCap != nil {
gasFeeCap = tc.gasFeeCap
}
if tc.gasTipCap == nil {
gasTipCap = oneInt.BigInt()
} else {
gasTipCap = tc.gasTipCap
}
suite.app.EvmKeeper.AddBalance(suite.address, hundredBaseFeeInt.BigInt())
balance := suite.app.EvmKeeper.GetBalance(suite.address)
suite.Require().Equal(balance, hundredBaseFeeInt.BigInt())
} else {
if tc.gasPrice != nil {
gasPrice = tc.gasPrice.BigInt()
}
suite.app.EvmKeeper.AddBalance(suite.address, hundredInt.BigInt())
balance := suite.app.EvmKeeper.GetBalance(suite.address)
suite.Require().Equal(balance, hundredInt.BigInt())
}
tx := evmtypes.NewTx(zeroInt.BigInt(), 1, &suite.address, amount, tc.gasLimit, gasPrice, nil, nil, nil, tc.accessList)
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)
@@ -242,23 +407,37 @@ func (suite *KeeperTestSuite) TestDeductTxCostsFromUserBalance() {
evmtypes.DefaultEVMDenom,
false,
false,
false, // london
suite.dynamicTxFee, // london
)
if tc.expectPass {
suite.Require().NoError(err, "valid test %d failed", i)
suite.Require().Equal(
fees,
sdk.NewCoins(
sdk.NewCoin(evmtypes.DefaultEVMDenom, tc.gasPrice.Mul(sdk.NewIntFromUint64(tc.gasLimit))),
),
"valid test %d failed, fee value is wrong ", i,
)
if tc.dynamicTxFee {
baseFee := suite.app.FeeMarketKeeper.GetBaseFee(suite.ctx)
gasFeeGap := new(big.Int).Sub(txData.GetGasFeeCap(), baseFee)
effectiveTip := cmath.BigMin(txData.GetGasTipCap(), gasFeeGap)
suite.Require().Equal(
fees,
sdk.NewCoins(
sdk.NewCoin(evmtypes.DefaultEVMDenom, sdk.NewIntFromBigInt(effectiveTip).Mul(sdk.NewIntFromUint64(tc.gasLimit))),
),
"valid test %d failed, fee value is wrong ", i,
)
} else {
suite.Require().Equal(
fees,
sdk.NewCoins(
sdk.NewCoin(evmtypes.DefaultEVMDenom, tc.gasPrice.Mul(sdk.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.dynamicTxFee = false // reset flag
}
+1 -1
View File
@@ -94,7 +94,7 @@ func newMsgEthereumTx(
}
case accesses != nil && gasFeeCap != nil && gasTipCap != nil:
gtc := sdk.NewIntFromBigInt(gasTipCap)
gfc := sdk.NewIntFromBigInt(gasTipCap)
gfc := sdk.NewIntFromBigInt(gasFeeCap)
txData = &DynamicFeeTx{
ChainID: cid,