forked from cerc-io/laconicd-deprecated
		
	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:
		
							parent
							
								
									2f531af3f2
								
							
						
					
					
						commit
						1076307e6b
					
				| @ -55,6 +55,7 @@ Ref: https://keepachangelog.com/en/1.0.0/ | ||||
| * (rpc, test) [tharsis#608](https://github.com/tharsis/ethermint/pull/608) Fix rpc test. | ||||
| * (rpc) [tharsis#661](https://github.com/tharsis/ethermint/pull/661) Fix OOM bug when creating too many filters using JSON-RPC. | ||||
| * (evm) [tharsis#660](https://github.com/tharsis/ethermint/pull/660) Fix `nil` pointer panic in `ApplyNativeMessage`. | ||||
| * (evm, test) [tharsis#649](https://github.com/tharsis/ethermint/pull/649) Test DynamicFeeTx. | ||||
| 
 | ||||
| ## [v0.7.0] - 2021-10-07 | ||||
| 
 | ||||
|  | ||||
| @ -6,11 +6,16 @@ import ( | ||||
| 
 | ||||
| 	sdk "github.com/cosmos/cosmos-sdk/types" | ||||
| 
 | ||||
| 	"github.com/ethereum/go-ethereum/core/types" | ||||
| 	ethparams "github.com/ethereum/go-ethereum/params" | ||||
| 	"github.com/tharsis/ethermint/tests" | ||||
| 	evmtypes "github.com/tharsis/ethermint/x/evm/types" | ||||
| ) | ||||
| 
 | ||||
| func (suite AnteTestSuite) TestAnteHandler() { | ||||
| 	suite.dynamicTxFee = false | ||||
| 	suite.SetupTest() // reset
 | ||||
| 
 | ||||
| 	addr, privKey := tests.NewAddrKey() | ||||
| 	to := tests.GenerateAddress() | ||||
| 
 | ||||
| @ -145,3 +150,242 @@ func (suite AnteTestSuite) TestAnteHandler() { | ||||
| 		}) | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| func (suite AnteTestSuite) TestAnteHandlerWithDynamicTxFee() { | ||||
| 	suite.dynamicTxFee = true | ||||
| 	suite.SetupTest() // reset
 | ||||
| 
 | ||||
| 	addr, privKey := tests.NewAddrKey() | ||||
| 	to := tests.GenerateAddress() | ||||
| 
 | ||||
| 	acc := suite.app.AccountKeeper.NewAccountWithAddress(suite.ctx, addr.Bytes()) | ||||
| 	suite.Require().NoError(acc.SetSequence(1)) | ||||
| 	suite.app.AccountKeeper.SetAccount(suite.ctx, acc) | ||||
| 
 | ||||
| 	suite.app.EvmKeeper.AddBalance(addr, big.NewInt((ethparams.InitialBaseFee+10)*100000)) | ||||
| 
 | ||||
| 	testCases := []struct { | ||||
| 		name      string | ||||
| 		txFn      func() sdk.Tx | ||||
| 		checkTx   bool | ||||
| 		reCheckTx bool | ||||
| 		expPass   bool | ||||
| 	}{ | ||||
| 		{ | ||||
| 			"success - DeliverTx (contract)", | ||||
| 			func() sdk.Tx { | ||||
| 				signedContractTx := | ||||
| 					evmtypes.NewTxContract( | ||||
| 						suite.app.EvmKeeper.ChainID(), | ||||
| 						1, | ||||
| 						big.NewInt(10), | ||||
| 						100000, | ||||
| 						nil, | ||||
| 						big.NewInt(ethparams.InitialBaseFee+1), | ||||
| 						big.NewInt(1), | ||||
| 						nil, | ||||
| 						&types.AccessList{}, | ||||
| 					) | ||||
| 				signedContractTx.From = addr.Hex() | ||||
| 
 | ||||
| 				tx := suite.CreateTestTx(signedContractTx, privKey, 1, true) | ||||
| 				return tx | ||||
| 			}, | ||||
| 			false, false, true, | ||||
| 		}, | ||||
| 		{ | ||||
| 			"success - CheckTx (contract)", | ||||
| 			func() sdk.Tx { | ||||
| 				signedContractTx := | ||||
| 					evmtypes.NewTxContract( | ||||
| 						suite.app.EvmKeeper.ChainID(), | ||||
| 						1, | ||||
| 						big.NewInt(10), | ||||
| 						100000, | ||||
| 						nil, | ||||
| 						big.NewInt(ethparams.InitialBaseFee+1), | ||||
| 						big.NewInt(1), | ||||
| 						nil, | ||||
| 						&types.AccessList{}, | ||||
| 					) | ||||
| 				signedContractTx.From = addr.Hex() | ||||
| 
 | ||||
| 				tx := suite.CreateTestTx(signedContractTx, privKey, 1, true) | ||||
| 				return tx | ||||
| 			}, | ||||
| 			true, false, true, | ||||
| 		}, | ||||
| 		{ | ||||
| 			"success - ReCheckTx (contract)", | ||||
| 			func() sdk.Tx { | ||||
| 				signedContractTx := | ||||
| 					evmtypes.NewTxContract( | ||||
| 						suite.app.EvmKeeper.ChainID(), | ||||
| 						1, | ||||
| 						big.NewInt(10), | ||||
| 						100000, | ||||
| 						nil, | ||||
| 						big.NewInt(ethparams.InitialBaseFee+1), | ||||
| 						big.NewInt(1), | ||||
| 						nil, | ||||
| 						&types.AccessList{}, | ||||
| 					) | ||||
| 				signedContractTx.From = addr.Hex() | ||||
| 
 | ||||
| 				tx := suite.CreateTestTx(signedContractTx, privKey, 1, true) | ||||
| 				return tx | ||||
| 			}, | ||||
| 			false, true, true, | ||||
| 		}, | ||||
| 		{ | ||||
| 			"success - DeliverTx", | ||||
| 			func() sdk.Tx { | ||||
| 				signedTx := | ||||
| 					evmtypes.NewTx( | ||||
| 						suite.app.EvmKeeper.ChainID(), | ||||
| 						1, | ||||
| 						&to, | ||||
| 						big.NewInt(10), | ||||
| 						100000, | ||||
| 						nil, | ||||
| 						big.NewInt(ethparams.InitialBaseFee+1), | ||||
| 						big.NewInt(1), | ||||
| 						nil, | ||||
| 						&types.AccessList{}, | ||||
| 					) | ||||
| 				signedTx.From = addr.Hex() | ||||
| 
 | ||||
| 				tx := suite.CreateTestTx(signedTx, privKey, 1, true) | ||||
| 				return tx | ||||
| 			}, | ||||
| 			false, false, true, | ||||
| 		}, | ||||
| 		{ | ||||
| 			"success - CheckTx", | ||||
| 			func() sdk.Tx { | ||||
| 				signedTx := | ||||
| 					evmtypes.NewTx( | ||||
| 						suite.app.EvmKeeper.ChainID(), | ||||
| 						2, | ||||
| 						&to, | ||||
| 						big.NewInt(10), | ||||
| 						100000, | ||||
| 						nil, | ||||
| 						big.NewInt(ethparams.InitialBaseFee+1), | ||||
| 						big.NewInt(1), | ||||
| 						nil, | ||||
| 						&types.AccessList{}, | ||||
| 					) | ||||
| 				signedTx.From = addr.Hex() | ||||
| 
 | ||||
| 				tx := suite.CreateTestTx(signedTx, privKey, 1, true) | ||||
| 				return tx | ||||
| 			}, | ||||
| 			true, false, true, | ||||
| 		}, | ||||
| 		{ | ||||
| 			"success - ReCheckTx", | ||||
| 			func() sdk.Tx { | ||||
| 				signedTx := | ||||
| 					evmtypes.NewTx( | ||||
| 						suite.app.EvmKeeper.ChainID(), | ||||
| 						3, | ||||
| 						&to, | ||||
| 						big.NewInt(10), | ||||
| 						100000, | ||||
| 						nil, | ||||
| 						big.NewInt(ethparams.InitialBaseFee+1), | ||||
| 						big.NewInt(1), | ||||
| 						nil, | ||||
| 						&types.AccessList{}, | ||||
| 					) | ||||
| 				signedTx.From = addr.Hex() | ||||
| 
 | ||||
| 				tx := suite.CreateTestTx(signedTx, privKey, 1, true) | ||||
| 				return tx | ||||
| 			}, false, true, true, | ||||
| 		}, | ||||
| 		{ | ||||
| 			"success - CheckTx (cosmos tx not signed)", | ||||
| 			func() sdk.Tx { | ||||
| 				signedTx := | ||||
| 					evmtypes.NewTx( | ||||
| 						suite.app.EvmKeeper.ChainID(), | ||||
| 						4, | ||||
| 						&to, | ||||
| 						big.NewInt(10), | ||||
| 						100000, | ||||
| 						nil, | ||||
| 						big.NewInt(ethparams.InitialBaseFee+1), | ||||
| 						big.NewInt(1), | ||||
| 						nil, | ||||
| 						&types.AccessList{}, | ||||
| 					) | ||||
| 				signedTx.From = addr.Hex() | ||||
| 
 | ||||
| 				tx := suite.CreateTestTx(signedTx, privKey, 1, false) | ||||
| 				return tx | ||||
| 			}, false, true, true, | ||||
| 		}, | ||||
| 		{ | ||||
| 			"fail - CheckTx (cosmos tx is not valid)", | ||||
| 			func() sdk.Tx { | ||||
| 				signedTx := | ||||
| 					evmtypes.NewTx( | ||||
| 						suite.app.EvmKeeper.ChainID(), | ||||
| 						4, | ||||
| 						&to, | ||||
| 						big.NewInt(10), | ||||
| 						100000, | ||||
| 						nil, | ||||
| 						big.NewInt(ethparams.InitialBaseFee+1), | ||||
| 						big.NewInt(1), | ||||
| 						nil, | ||||
| 						&types.AccessList{}, | ||||
| 					) | ||||
| 				signedTx.From = addr.Hex() | ||||
| 
 | ||||
| 				txBuilder := suite.CreateTestTxBuilder(signedTx, privKey, 1, false) | ||||
| 				// bigger than MaxGasWanted
 | ||||
| 				txBuilder.SetGasLimit(uint64(1 << 63)) | ||||
| 				return txBuilder.GetTx() | ||||
| 			}, false, true, false, | ||||
| 		}, | ||||
| 		{ | ||||
| 			"fail - CheckTx (memo too long)", | ||||
| 			func() sdk.Tx { | ||||
| 				signedTx := | ||||
| 					evmtypes.NewTx( | ||||
| 						suite.app.EvmKeeper.ChainID(), | ||||
| 						5, | ||||
| 						&to, | ||||
| 						big.NewInt(10), | ||||
| 						100000, | ||||
| 						nil, | ||||
| 						big.NewInt(ethparams.InitialBaseFee+1), | ||||
| 						big.NewInt(1), | ||||
| 						nil, | ||||
| 						&types.AccessList{}, | ||||
| 					) | ||||
| 				signedTx.From = addr.Hex() | ||||
| 
 | ||||
| 				txBuilder := suite.CreateTestTxBuilder(signedTx, privKey, 1, true) | ||||
| 				txBuilder.SetMemo(strings.Repeat("*", 257)) | ||||
| 				return txBuilder.GetTx() | ||||
| 			}, true, false, false, | ||||
| 		}, | ||||
| 	} | ||||
| 
 | ||||
| 	for _, tc := range testCases { | ||||
| 		suite.Run(tc.name, func() { | ||||
| 			suite.ctx = suite.ctx.WithIsCheckTx(tc.reCheckTx).WithIsReCheckTx(tc.reCheckTx) | ||||
| 			_, err := suite.anteHandler(suite.ctx, tc.txFn(), false) | ||||
| 			if tc.expPass { | ||||
| 				suite.Require().NoError(err) | ||||
| 			} else { | ||||
| 				suite.Require().Error(err) | ||||
| 			} | ||||
| 		}) | ||||
| 	} | ||||
| 	suite.dynamicTxFee = false | ||||
| } | ||||
|  | ||||
| @ -24,6 +24,7 @@ import ( | ||||
| 	"github.com/tharsis/ethermint/encoding" | ||||
| 	"github.com/tharsis/ethermint/tests" | ||||
| 	evmtypes "github.com/tharsis/ethermint/x/evm/types" | ||||
| 	feemarkettypes "github.com/tharsis/ethermint/x/feemarket/types" | ||||
| 
 | ||||
| 	tmproto "github.com/tendermint/tendermint/proto/tendermint/types" | ||||
| ) | ||||
| @ -31,16 +32,28 @@ import ( | ||||
| type AnteTestSuite struct { | ||||
| 	suite.Suite | ||||
| 
 | ||||
| 	ctx         sdk.Context | ||||
| 	app         *app.EthermintApp | ||||
| 	clientCtx   client.Context | ||||
| 	anteHandler sdk.AnteHandler | ||||
| 	ethSigner   ethtypes.Signer | ||||
| 	ctx          sdk.Context | ||||
| 	app          *app.EthermintApp | ||||
| 	clientCtx    client.Context | ||||
| 	anteHandler  sdk.AnteHandler | ||||
| 	ethSigner    ethtypes.Signer | ||||
| 	dynamicTxFee bool | ||||
| } | ||||
| 
 | ||||
| func (suite *AnteTestSuite) SetupTest() { | ||||
| 	checkTx := false | ||||
| 	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: 2, ChainID: "ethermint_9000-1", Time: time.Now().UTC()}) | ||||
| 	suite.ctx = suite.ctx.WithMinGasPrices(sdk.NewDecCoins(sdk.NewDecCoin(evmtypes.DefaultEVMDenom, sdk.OneInt()))) | ||||
| 	suite.ctx = suite.ctx.WithBlockGasMeter(sdk.NewGasMeter(1000000000000000000)) | ||||
|  | ||||
| @ -12,6 +12,7 @@ import ( | ||||
| 	tmproto "github.com/tendermint/tendermint/proto/tendermint/types" | ||||
| 	tmtypes "github.com/tendermint/tendermint/types" | ||||
| 	dbm "github.com/tendermint/tm-db" | ||||
| 	feemarkettypes "github.com/tharsis/ethermint/x/feemarket/types" | ||||
| ) | ||||
| 
 | ||||
| // DefaultConsensusParams defines the default Tendermint consensus params used in
 | ||||
| @ -34,12 +35,22 @@ var DefaultConsensusParams = &abci.ConsensusParams{ | ||||
| } | ||||
| 
 | ||||
| // Setup initializes a new EthermintApp. A Nop logger is set in EthermintApp.
 | ||||
| func Setup(isCheckTx bool) *EthermintApp { | ||||
| func Setup(isCheckTx bool, feemarketGenesis *feemarkettypes.GenesisState) *EthermintApp { | ||||
| 	db := dbm.NewMemDB() | ||||
| 	app := NewEthermintApp(log.NewNopLogger(), db, nil, true, map[int64]bool{}, DefaultNodeHome, 5, encoding.MakeConfig(ModuleBasics), simapp.EmptyAppOptions{}) | ||||
| 	if !isCheckTx { | ||||
| 		// init chain must be called to stop deliverState from being nil
 | ||||
| 		genesisState := NewDefaultGenesisState() | ||||
| 
 | ||||
| 		// Verify feeMarket genesis
 | ||||
| 		if feemarketGenesis != nil { | ||||
| 			if err := feemarketGenesis.Validate(); err != nil { | ||||
| 				panic(err) | ||||
| 			} | ||||
| 
 | ||||
| 			genesisState[feemarkettypes.ModuleName] = app.AppCodec().MustMarshalJSON(feemarketGenesis) | ||||
| 		} | ||||
| 
 | ||||
| 		stateBytes, err := json.MarshalIndent(genesisState, "", " ") | ||||
| 		if err != nil { | ||||
| 			panic(err) | ||||
|  | ||||
| @ -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()) | ||||
|  | ||||
| @ -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
 | ||||
| } | ||||
|  | ||||
| @ -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
 | ||||
| 			ðtypes.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, | ||||
| 			ðtypes.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 = ðtypes.LegacyTx{ | ||||
| 	Data:     []byte{}, | ||||
| } | ||||
| 
 | ||||
| var templateDynamicFeeTx = ðtypes.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) | ||||
| 
 | ||||
|  | ||||
| @ -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, | ||||
| 			ðtypes.Log{ | ||||
| 				Address: addr, | ||||
| 			}, | ||||
| 			ðtypes.Log{ | ||||
| 				Address: addr, | ||||
| 				TxHash:  txHash3, | ||||
| 			}, | ||||
| 			func() {}, | ||||
| 		}, | ||||
| 		{ | ||||
| 			"log index keep increasing in new dynamicfee tx", | ||||
| 			txHash4, | ||||
| 			ðtypes.Log{ | ||||
| 				Address: addr, | ||||
| 			}, | ||||
| 			ðtypes.Log{ | ||||
| 				Address: addr, | ||||
| 				TxHash:  txHash4, | ||||
| 				TxIndex: 1, | ||||
| 				Index:   1, | ||||
| 			}, | ||||
| 			func() { | ||||
| 				suite.app.EvmKeeper.SetTxHashTransient(txHash) | ||||
| 				suite.app.EvmKeeper.AddLog(ðtypes.Log{ | ||||
| 					Address: addr, | ||||
| 				}) | ||||
| 				suite.app.EvmKeeper.IncreaseTxIndexTransient() | ||||
| 			}, | ||||
| 		}, | ||||
| 	} | ||||
| 
 | ||||
| 	for _, tc := range testCases { | ||||
|  | ||||
| @ -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()) | ||||
|  | ||||
| @ -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: ðtypes.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:   ðtypes.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:   ðtypes.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:   ðtypes.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:   ðtypes.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:   ðtypes.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:   ðtypes.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:   ðtypes.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:   ðtypes.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: ðtypes.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:   ðtypes.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:   ðtypes.AccessList{}, | ||||
| 			expectPass:   false, | ||||
| 			dynamicTxFee: true, | ||||
| 		}, | ||||
| 		{ | ||||
| 			name:         "effectiveTip equal to gasTipCap", | ||||
| 			gasLimit:     100, | ||||
| 			gasFeeCap:    big.NewInt(ethparams.InitialBaseFee + 2), | ||||
| 			cost:         &oneInt, | ||||
| 			accessList:   ðtypes.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:   ðtypes.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
 | ||||
| } | ||||
|  | ||||
| @ -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, | ||||
|  | ||||
		Loading…
	
		Reference in New Issue
	
	Block a user