diff --git a/CHANGELOG.md b/CHANGELOG.md index a955d102f..c2cef05d5 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -52,6 +52,7 @@ - [\#685](https://github.com/cosmos/evm/pull/685) Add EIP-7702 e2e test - [\#680](https://github.com/cosmos/evm/pull/680) Introduce a `StaticPrecompiles` builder - [\#701](https://github.com/cosmos/evm/pull/701) Add address codec support to ERC20 IBC callbacks to handle hex addresses in addition to bech32 addresses. +- [\#702](https://github.com/cosmos/evm/pull/702) Fix mempool e2e test - [\#704](https://github.com/cosmos/evm/pull/704) Fix EIP-7702 test cases ### FEATURES diff --git a/tests/systemtests/Makefile b/tests/systemtests/Makefile index dd8f050a4..92f8375cb 100644 --- a/tests/systemtests/Makefile +++ b/tests/systemtests/Makefile @@ -3,5 +3,5 @@ WAIT_TIME ?= 20s test: - go test -mod=readonly -failfast -timeout=15m -tags='system_test' ./... --wait-time=$(WAIT_TIME) --verbose --binary evmd --chain-id local-4221 + go test -mod=readonly -failfast -timeout=25m -tags='system_test' ./... --wait-time=$(WAIT_TIME) --verbose --binary evmd --chain-id local-4221 diff --git a/tests/systemtests/main_test.go b/tests/systemtests/main_test.go index 74c412db6..295500a49 100644 --- a/tests/systemtests/main_test.go +++ b/tests/systemtests/main_test.go @@ -21,6 +21,7 @@ func TestTxsOrdering(t *testing.T) { func TestTxsReplacement(t *testing.T) { mempool.TestTxsReplacement(t) + mempool.TestTxsReplacementWithCosmosTx(t) mempool.TestMixedTxsReplacementEVMAndCosmos(t) mempool.TestMixedTxsReplacementLegacyAndDynamicFee(t) } diff --git a/tests/systemtests/mempool/test_exceptions.go b/tests/systemtests/mempool/test_exceptions.go index 87ec31741..31e9a2f57 100644 --- a/tests/systemtests/mempool/test_exceptions.go +++ b/tests/systemtests/mempool/test_exceptions.go @@ -12,7 +12,6 @@ func TestTxRebroadcasting(t *testing.T) { testCases := []struct { name string actions []func(s TestSuite) - bypass bool }{ { name: "ordering of pending txs %s", @@ -77,10 +76,6 @@ func TestTxRebroadcasting(t *testing.T) { for _, tc := range testCases { testName := fmt.Sprintf(tc.name, to.Description) t.Run(testName, func(t *testing.T) { - if tc.bypass { - return - } - s.BeforeEachCase(t) for _, action := range tc.actions { action(s) @@ -96,7 +91,6 @@ func TestMinimumGasPricesZero(t *testing.T) { testCases := []struct { name string actions []func(s TestSuite) - bypass bool }{ { name: "sequencial pending txs %s", @@ -138,10 +132,6 @@ func TestMinimumGasPricesZero(t *testing.T) { for _, tc := range testCases { testName := fmt.Sprintf(tc.name, to.Description) t.Run(testName, func(t *testing.T) { - if tc.bypass { - return - } - s.BeforeEachCase(t) for _, action := range tc.actions { action(s) diff --git a/tests/systemtests/mempool/test_ordering.go b/tests/systemtests/mempool/test_ordering.go index 4e92bc01c..b0ba8f7c6 100644 --- a/tests/systemtests/mempool/test_ordering.go +++ b/tests/systemtests/mempool/test_ordering.go @@ -13,7 +13,6 @@ func TestTxsOrdering(t *testing.T) { testCases := []struct { name string actions []func(s TestSuite) - bypass bool }{ { name: "ordering of pending txs %s", @@ -66,10 +65,6 @@ func TestTxsOrdering(t *testing.T) { for _, tc := range testCases { testName := fmt.Sprintf(tc.name, to.Description) t.Run(testName, func(t *testing.T) { - if tc.bypass { - return - } - s.BeforeEachCase(t) for _, action := range tc.actions { action(s) diff --git a/tests/systemtests/mempool/test_replacement.go b/tests/systemtests/mempool/test_replacement.go index dd53efcd2..a369c89ab 100644 --- a/tests/systemtests/mempool/test_replacement.go +++ b/tests/systemtests/mempool/test_replacement.go @@ -13,7 +13,6 @@ func TestTxsReplacement(t *testing.T) { testCases := []struct { name string actions []func(s TestSuite) - bypass bool }{ { name: "single pending tx submitted to same nodes %s", @@ -21,13 +20,12 @@ func TestTxsReplacement(t *testing.T) { func(s TestSuite) { _, err := s.SendTx(t, s.Node(0), "acc0", 0, s.BaseFee(), nil) require.NoError(t, err, "failed to send tx") - tx2, err := s.SendTx(t, s.Node(0), "acc0", 0, s.BaseFeeX2(), big.NewInt(1)) + tx2, err := s.SendTx(t, s.Node(1), "acc0", 0, s.BaseFeeX2(), big.NewInt(1)) require.NoError(t, err, "failed to send tx") s.SetExpPendingTxs(tx2) }, }, - bypass: true, }, { name: "multiple pending txs submitted to same nodes %s", @@ -35,23 +33,22 @@ func TestTxsReplacement(t *testing.T) { func(s TestSuite) { _, err := s.SendTx(t, s.Node(0), "acc0", 0, s.BaseFee(), nil) require.NoError(t, err, "failed to send tx") - tx2, err := s.SendTx(t, s.Node(0), "acc0", 0, s.BaseFeeX2(), big.NewInt(1)) + tx2, err := s.SendTx(t, s.Node(1), "acc0", 0, s.BaseFeeX2(), big.NewInt(1)) require.NoError(t, err, "failed to send tx") - _, err = s.SendTx(t, s.Node(1), "acc0", 1, s.BaseFee(), nil) + _, err = s.SendTx(t, s.Node(0), "acc0", 1, s.BaseFee(), nil) require.NoError(t, err, "failed to send tx") tx4, err := s.SendTx(t, s.Node(1), "acc0", 1, s.BaseFeeX2(), big.NewInt(1)) require.NoError(t, err, "failed to send tx") - _, err = s.SendTx(t, s.Node(2), "acc0", 2, s.BaseFee(), nil) + _, err = s.SendTx(t, s.Node(0), "acc0", 2, s.BaseFee(), nil) require.NoError(t, err, "failed to send tx") - tx6, err := s.SendTx(t, s.Node(2), "acc0", 2, s.BaseFeeX2(), big.NewInt(1)) + tx6, err := s.SendTx(t, s.Node(1), "acc0", 2, s.BaseFeeX2(), big.NewInt(1)) require.NoError(t, err, "failed to send tx") s.SetExpPendingTxs(tx2, tx4, tx6) }, }, - bypass: true, }, { name: "single queued tx %s", @@ -116,11 +113,6 @@ func TestTxsReplacement(t *testing.T) { TxType: suite.TxTypeEVM, IsDynamicFeeTx: true, }, - { - Description: "Cosmos LegacyTx", - TxType: suite.TxTypeCosmos, - IsDynamicFeeTx: false, - }, } s := suite.NewSystemTestSuite(t) @@ -131,10 +123,105 @@ func TestTxsReplacement(t *testing.T) { for _, tc := range testCases { testName := fmt.Sprintf(tc.name, to.Description) t.Run(testName, func(t *testing.T) { - if tc.bypass { - return + s.BeforeEachCase(t) + for _, action := range tc.actions { + action(s) + s.AfterEachAction(t) } + s.AfterEachCase(t) + }) + } + } +} + +func TestTxsReplacementWithCosmosTx(t *testing.T) { + testCases := []struct { + name string + actions []func(s TestSuite) + }{ + { + name: "single pending tx submitted to same nodes %s", + actions: []func(s TestSuite){ + func(s TestSuite) { + s.AwaitNBlocks(t, 2) + + // NOTE: Currently EVMD cannot handle tx reordering correctly when cosmos tx is used. + // It is because of CheckTxHandler cannot handle errors from SigVerificationDecorator properly. + // After modifying CheckTxHandler, we can also modify this test case + // : high prio cosmos tx should replace low prio evm tx. + tx1, err := s.SendTx(t, s.Node(0), "acc0", 0, s.BaseFee(), nil) + require.NoError(t, err, "failed to send tx") + _, err = s.SendTx(t, s.Node(1), "acc0", 0, s.BaseFeeX2(), big.NewInt(1)) + require.NoError(t, err, "failed to send tx") + + s.SetExpPendingTxs(tx1) + }, + }, + }, + { + name: "multiple pending txs submitted to same nodes %s", + actions: []func(s TestSuite){ + func(s TestSuite) { + s.AwaitNBlocks(t, 2) + + // NOTE: Currently EVMD cannot handle tx reordering correctly when cosmos tx is used. + // It is because of CheckTxHandler cannot handle errors from SigVerificationDecorator properly. + // After modifying CheckTxHandler, we can also modify this test case + // : high prio cosmos tx should replace low prio evm tx. + tx1, err := s.SendTx(t, s.Node(0), "acc0", 0, s.BaseFee(), nil) + require.NoError(t, err, "failed to send tx") + _, err = s.SendTx(t, s.Node(1), "acc0", 0, s.BaseFeeX2(), big.NewInt(1)) + require.NoError(t, err, "failed to send tx") + + tx3, err := s.SendTx(t, s.Node(0), "acc0", 1, s.BaseFee(), nil) + require.NoError(t, err, "failed to send tx") + _, err = s.SendTx(t, s.Node(1), "acc0", 1, s.BaseFeeX2(), big.NewInt(1)) + require.NoError(t, err, "failed to send tx") + + tx5, err := s.SendTx(t, s.Node(0), "acc0", 2, s.BaseFee(), nil) + require.NoError(t, err, "failed to send tx") + _, err = s.SendTx(t, s.Node(1), "acc0", 2, s.BaseFeeX2(), big.NewInt(1)) + require.NoError(t, err, "failed to send tx") + s.SetExpPendingTxs(tx1, tx3, tx5) + }, + }, + }, + { + name: "single queued tx %s", + actions: []func(s TestSuite){ + func(s TestSuite) { + // Cosmos txs are not queued in local mempool + _, err := s.SendTx(t, s.Node(0), "acc0", 1, s.BaseFee(), nil) + require.NoError(t, err, "failed to send tx") + _, err = s.SendTx(t, s.Node(0), "acc0", 1, s.BaseFeeX2(), big.NewInt(1)) + require.NoError(t, err, "failed to send tx") + }, + func(s TestSuite) { + txHash, err := s.SendTx(t, s.Node(1), "acc0", 0, s.BaseFee(), nil) + require.NoError(t, err, "failed to send tx") + + s.SetExpPendingTxs(txHash) + }, + }, + }, + } + + testOptions := []*suite.TestOptions{ + { + Description: "Cosmos LegacyTx", + TxType: suite.TxTypeCosmos, + }, + } + + s := suite.NewSystemTestSuite(t) + s.SetupTest(t) + + for _, to := range testOptions { + s.SetOptions(to) + for _, tc := range testCases { + testName := fmt.Sprintf(tc.name, to.Description) + t.Run(testName, func(t *testing.T) { s.BeforeEachCase(t) for _, action := range tc.actions { action(s) @@ -150,35 +237,36 @@ func TestMixedTxsReplacementEVMAndCosmos(t *testing.T) { testCases := []struct { name string actions []func(s TestSuite) - bypass bool }{ { name: "single pending tx (low prio evm tx first) %s", actions: []func(s TestSuite){ func(s TestSuite) { - _, err := s.SendEthTx(t, s.Node(0), "acc0", 0, s.BaseFee(), nil) + s.AwaitNBlocks(t, 2) + + tx1, err := s.SendEthTx(t, s.Node(0), "acc0", 0, s.BaseFee(), s.BaseFee()) require.NoError(t, err, "failed to send tx") - tx2, err := s.SendCosmosTx(t, s.Node(0), "acc0", 0, s.BaseFeeX2(), big.NewInt(1)) + + baseFeeX20 := new(big.Int).Mul(s.BaseFeeX2(), big.NewInt(1000000000000000000)) + _, err = s.SendCosmosTx(t, s.Node(1), "acc0", 0, baseFeeX20, nil) require.NoError(t, err, "failed to send tx") - s.SetExpPendingTxs(tx2) + s.SetExpPendingTxs(tx1) }, }, - bypass: true, }, { name: "single pending tx (high prio evm tx first) %s", actions: []func(s TestSuite){ func(s TestSuite) { - tx1, err := s.SendEthTx(t, s.Node(0), "acc0", 0, s.BaseFeeX2(), big.NewInt(1)) + tx1, err := s.SendEthTx(t, s.Node(0), "acc0", 0, s.BaseFeeX2(), s.BaseFeeX2()) require.NoError(t, err, "failed to send tx") - _, err = s.SendCosmosTx(t, s.Node(0), "acc0", 0, s.BaseFee(), nil) + _, err = s.SendCosmosTx(t, s.Node(1), "acc0", 0, s.BaseFee(), nil) require.NoError(t, err, "failed to send tx") s.SetExpPendingTxs(tx1) }, }, - bypass: true, }, { name: "single pending tx (low prio cosmos tx first) %s", @@ -186,19 +274,19 @@ func TestMixedTxsReplacementEVMAndCosmos(t *testing.T) { func(s TestSuite) { _, err := s.SendCosmosTx(t, s.Node(0), "acc0", 0, s.BaseFee(), nil) require.NoError(t, err, "failed to send tx") - tx2, err := s.SendEthTx(t, s.Node(0), "acc0", 0, s.BaseFeeX2(), big.NewInt(1)) + tx2, err := s.SendEthTx(t, s.Node(1), "acc0", 0, s.BaseFeeX2(), s.BaseFeeX2()) require.NoError(t, err, "failed to send tx") s.SetExpPendingTxs(tx2) }, }, - bypass: true, }, { name: "single pending tx (high prio cosmos tx first) %s", actions: []func(s TestSuite){ func(s TestSuite) { - tx1, err := s.SendCosmosTx(t, s.Node(0), "acc0", 0, s.BaseFeeX2(), big.NewInt(1)) + baseFeeX20 := new(big.Int).Mul(s.BaseFeeX2(), big.NewInt(10)) + tx1, err := s.SendCosmosTx(t, s.Node(0), "acc0", 0, baseFeeX20, nil) require.NoError(t, err, "failed to send tx") _, err = s.SendEthTx(t, s.Node(0), "acc0", 0, s.BaseFee(), nil) require.NoError(t, err, "failed to send tx") @@ -206,7 +294,6 @@ func TestMixedTxsReplacementEVMAndCosmos(t *testing.T) { s.SetExpPendingTxs(tx1) }, }, - bypass: true, }, { name: "single queued tx (low prio evm tx first) %s", @@ -256,7 +343,7 @@ func TestMixedTxsReplacementEVMAndCosmos(t *testing.T) { func(s TestSuite) { _, err := s.SendCosmosTx(t, s.Node(0), "acc0", 1, s.BaseFee(), nil) require.NoError(t, err, "failed to send tx") - tx2, err := s.SendEthTx(t, s.Node(0), "acc0", 1, s.BaseFeeX2(), big.NewInt(1)) + tx2, err := s.SendEthTx(t, s.Node(0), "acc0", 1, s.BaseFeeX2(), s.BaseFeeX2()) require.NoError(t, err, "failed to send tx") // CosmosTx is not queued in local mempool @@ -312,10 +399,6 @@ func TestMixedTxsReplacementEVMAndCosmos(t *testing.T) { for _, tc := range testCases { testName := fmt.Sprintf(tc.name, to.Description) t.Run(testName, func(t *testing.T) { - if tc.bypass { - return - } - s.BeforeEachCase(t) for _, action := range tc.actions { action(s) @@ -331,7 +414,6 @@ func TestMixedTxsReplacementLegacyAndDynamicFee(t *testing.T) { testCases := []struct { name string actions []func(s TestSuite) - bypass bool }{ { name: "dynamic fee tx should not replace legacy tx", @@ -410,10 +492,6 @@ func TestMixedTxsReplacementLegacyAndDynamicFee(t *testing.T) { for _, tc := range testCases { t.Run(tc.name, func(t *testing.T) { - if tc.bypass { - return - } - s.BeforeEachCase(t) for _, action := range tc.actions { action(s) diff --git a/tests/systemtests/suite/types.go b/tests/systemtests/suite/types.go index ee7e31c3f..698995c95 100644 --- a/tests/systemtests/suite/types.go +++ b/tests/systemtests/suite/types.go @@ -8,6 +8,7 @@ const ( NodeArgsApiEnable = "--api.enable=true" NodeArgsJsonrpcApi = "--json-rpc.api=eth,txpool,personal,net,debug,web3" NodeArgsJsonrpcAllowUnprotectedTxs = "--json-rpc.allow-unprotected-txs=true" + NodeArgsMinimumGasPrice = "--minimum-gas-prices=0.000001atest" ) // TestOptions defines the options for a test case. @@ -40,10 +41,20 @@ func DefaultNodeArgs() []string { NodeArgsChainID, NodeArgsApiEnable, NodeArgsJsonrpcAllowUnprotectedTxs, + NodeArgsMinimumGasPrice, } } // MinimumGasPriceZeroArgs returns the node arguments with minimum gas price set to zero. func MinimumGasPriceZeroArgs() []string { - return append(DefaultNodeArgs(), "--minimum-gas-prices=0stake") + defaultArgs := DefaultNodeArgs() + // Remove the default minimum gas price argument + var args []string + for _, arg := range defaultArgs { + if arg != NodeArgsMinimumGasPrice { + args = append(args, arg) + } + } + // Add the zero minimum gas price argument + return append(DefaultNodeArgs(), "--minimum-gas-prices=0atest") }