diff --git a/.changeset/short-gifts-eat.md b/.changeset/short-gifts-eat.md new file mode 100644 index 00000000000..afc171715d4 --- /dev/null +++ b/.changeset/short-gifts-eat.md @@ -0,0 +1,5 @@ +--- +"chainlink": patch +--- + +use last mined nonce instead of pending nonce to recover from occasional nonce gap issues within nonce tracker. #internal diff --git a/core/chains/evm/txmgr/broadcaster_test.go b/core/chains/evm/txmgr/broadcaster_test.go index bafe46fefc5..5b54373dfc6 100644 --- a/core/chains/evm/txmgr/broadcaster_test.go +++ b/core/chains/evm/txmgr/broadcaster_test.go @@ -91,7 +91,7 @@ func TestEthBroadcaster_Lifecycle(t *testing.T) { estimator := gasmocks.NewEvmFeeEstimator(t) txBuilder := txmgr.NewEvmTxAttemptBuilder(*ethClient.ConfiguredChainID(), evmcfg.EVM().GasEstimator(), ethKeyStore, estimator) txmClient := txmgr.NewEvmTxmClient(ethClient, nil) - ethClient.On("PendingNonceAt", mock.Anything, mock.Anything).Return(uint64(0), nil) + ethClient.On("NonceAt", mock.Anything, mock.Anything, mock.Anything).Return(uint64(0), nil).Twice() eb := txmgr.NewEvmBroadcaster( txStore, txmClient, @@ -149,7 +149,7 @@ func TestEthBroadcaster_LoadNextSequenceMapFailure_StartupSuccess(t *testing.T) cltest.MustInsertRandomKeyReturningState(t, ethKeyStore) estimator := gasmocks.NewEvmFeeEstimator(t) txBuilder := txmgr.NewEvmTxAttemptBuilder(*ethClient.ConfiguredChainID(), evmcfg.EVM().GasEstimator(), ethKeyStore, estimator) - ethClient.On("PendingNonceAt", mock.Anything, mock.Anything).Return(uint64(0), errors.New("Getting on-chain nonce failed")) + ethClient.On("NonceAt", mock.Anything, mock.Anything, mock.Anything).Return(uint64(0), errors.New("Getting on-chain nonce failed")).Once() txmClient := txmgr.NewEvmTxmClient(ethClient, nil) eb := txmgr.NewEvmBroadcaster( txStore, @@ -185,8 +185,8 @@ func TestEthBroadcaster_ProcessUnstartedEthTxs_Success(t *testing.T) { evmcfg := evmtest.NewChainScopedConfig(t, cfg) checkerFactory := &txmgr.CheckerFactory{Client: ethClient} - ethClient.On("PendingNonceAt", mock.Anything, fromAddress).Return(uint64(0), nil).Once() - ethClient.On("PendingNonceAt", mock.Anything, otherAddress).Return(uint64(0), nil).Once() + ethClient.On("NonceAt", mock.Anything, fromAddress, mock.Anything).Return(uint64(0), nil).Once() + ethClient.On("NonceAt", mock.Anything, otherAddress, mock.Anything).Return(uint64(0), nil).Once() lggr := logger.Test(t) nonceTracker := txmgr.NewNonceTracker(lggr, txStore, txmgr.NewEvmTxmClient(ethClient, nil)) eb := NewTestEthBroadcaster(t, txStore, ethClient, ethKeyStore, cfg, evmcfg, checkerFactory, false, nonceTracker) @@ -387,7 +387,7 @@ func TestEthBroadcaster_ProcessUnstartedEthTxs_Success(t *testing.T) { c.EVM[0].GasEstimator.PriceMax = assets.NewWeiI(rnd + 2) }) evmcfg = evmtest.NewChainScopedConfig(t, cfg) - ethClient.On("PendingNonceAt", mock.Anything, otherAddress).Return(uint64(1), nil).Once() + ethClient.On("NonceAt", mock.Anything, otherAddress, mock.Anything).Return(uint64(1), nil).Once() nonceTracker = txmgr.NewNonceTracker(lggr, txStore, txmgr.NewEvmTxmClient(ethClient, nil)) eb = NewTestEthBroadcaster(t, txStore, ethClient, ethKeyStore, cfg, evmcfg, checkerFactory, false, nonceTracker) @@ -556,7 +556,7 @@ func TestEthBroadcaster_TransmitChecking(t *testing.T) { ethClient := testutils.NewEthClientMockWithDefaultChain(t) evmcfg := evmtest.NewChainScopedConfig(t, cfg) checkerFactory := &testCheckerFactory{} - ethClient.On("PendingNonceAt", mock.Anything, fromAddress).Return(uint64(0), nil).Once() + ethClient.On("NonceAt", mock.Anything, fromAddress, mock.Anything).Return(uint64(0), nil).Once() nonceTracker := txmgr.NewNonceTracker(logger.Test(t), txStore, txmgr.NewEvmTxmClient(ethClient, nil)) eb := NewTestEthBroadcaster(t, txStore, ethClient, ethKeyStore, cfg, evmcfg, checkerFactory, false, nonceTracker) @@ -648,7 +648,7 @@ func TestEthBroadcaster_ProcessUnstartedEthTxs_OptimisticLockingOnEthTx(t *testi close(chStartEstimate) <-chBlock }).Once() - ethClient.On("PendingNonceAt", mock.Anything, fromAddress).Return(uint64(0), nil) + ethClient.On("NonceAt", mock.Anything, fromAddress, mock.Anything).Return(uint64(0), nil).Once() txmClient := txmgr.NewEvmTxmClient(ethClient, nil) eb := txmgr.NewEvmBroadcaster( txStore, @@ -706,7 +706,7 @@ func TestEthBroadcaster_ProcessUnstartedEthTxs_Success_WithMultiplier(t *testing evmcfg := evmtest.NewChainScopedConfig(t, cfg) ethClient := testutils.NewEthClientMockWithDefaultChain(t) - ethClient.On("PendingNonceAt", mock.Anything, fromAddress).Return(uint64(0), nil).Once() + ethClient.On("NonceAt", mock.Anything, fromAddress, mock.Anything).Return(uint64(0), nil).Once() nonceTracker := txmgr.NewNonceTracker(logger.Test(t), txStore, txmgr.NewEvmTxmClient(ethClient, nil)) eb := NewTestEthBroadcaster(t, txStore, ethClient, ethKeyStore, cfg, evmcfg, &testCheckerFactory{}, false, nonceTracker) @@ -788,7 +788,7 @@ func TestEthBroadcaster_ProcessUnstartedEthTxs_ResumingFromCrash(t *testing.T) { _, fromAddress := cltest.RandomKey{Nonce: nextNonce.Int64()}.MustInsertWithState(t, ethKeyStore) ethClient := testutils.NewEthClientMockWithDefaultChain(t) - ethClient.On("PendingNonceAt", mock.Anything, fromAddress).Return(uint64(0), nil).Once() + ethClient.On("NonceAt", mock.Anything, fromAddress, mock.Anything).Return(uint64(0), nil).Once() nonceTracker := txmgr.NewNonceTracker(logger.Test(t), txStore, txmgr.NewEvmTxmClient(ethClient, nil)) eb := NewTestEthBroadcaster(t, txStore, ethClient, ethKeyStore, cfg, evmcfg, &testCheckerFactory{}, false, nonceTracker) @@ -827,7 +827,7 @@ func TestEthBroadcaster_ProcessUnstartedEthTxs_ResumingFromCrash(t *testing.T) { _, fromAddress := cltest.RandomKey{Nonce: nextNonce.Int64()}.MustInsertWithState(t, ethKeyStore) ethClient := testutils.NewEthClientMockWithDefaultChain(t) - ethClient.On("PendingNonceAt", mock.Anything, fromAddress).Return(uint64(0), nil).Once() + ethClient.On("NonceAt", mock.Anything, fromAddress, mock.Anything).Return(uint64(0), nil).Once() nonceTracker := txmgr.NewNonceTracker(logger.Test(t), txStore, txmgr.NewEvmTxmClient(ethClient, nil)) eb := NewTestEthBroadcaster(t, txStore, ethClient, ethKeyStore, cfg, evmcfg, &testCheckerFactory{}, false, nonceTracker) @@ -864,7 +864,7 @@ func TestEthBroadcaster_ProcessUnstartedEthTxs_ResumingFromCrash(t *testing.T) { _, fromAddress := cltest.RandomKey{Nonce: nextNonce.Int64()}.MustInsertWithState(t, ethKeyStore) ethClient := testutils.NewEthClientMockWithDefaultChain(t) - ethClient.On("PendingNonceAt", mock.Anything, fromAddress).Return(uint64(0), nil).Once() + ethClient.On("NonceAt", mock.Anything, fromAddress, mock.Anything).Return(uint64(0), nil).Once() nonceTracker := txmgr.NewNonceTracker(logger.Test(t), txStore, txmgr.NewEvmTxmClient(ethClient, nil)) eb := NewTestEthBroadcaster(t, txStore, ethClient, ethKeyStore, cfg, evmcfg, &testCheckerFactory{}, false, nonceTracker) @@ -900,7 +900,7 @@ func TestEthBroadcaster_ProcessUnstartedEthTxs_ResumingFromCrash(t *testing.T) { _, fromAddress := cltest.RandomKey{Nonce: nextNonce.Int64()}.MustInsertWithState(t, ethKeyStore) ethClient := testutils.NewEthClientMockWithDefaultChain(t) - ethClient.On("PendingNonceAt", mock.Anything, fromAddress).Return(uint64(0), nil).Once() + ethClient.On("NonceAt", mock.Anything, fromAddress, mock.Anything).Return(uint64(0), nil).Once() nonceTracker := txmgr.NewNonceTracker(logger.Test(t), txStore, txmgr.NewEvmTxmClient(ethClient, nil)) eb := NewTestEthBroadcaster(t, txStore, ethClient, ethKeyStore, cfg, evmcfg, &testCheckerFactory{}, false, nonceTracker) @@ -938,7 +938,7 @@ func TestEthBroadcaster_ProcessUnstartedEthTxs_ResumingFromCrash(t *testing.T) { _, fromAddress := cltest.RandomKey{Nonce: nextNonce.Int64()}.MustInsertWithState(t, ethKeyStore) ethClient := testutils.NewEthClientMockWithDefaultChain(t) - ethClient.On("PendingNonceAt", mock.Anything, fromAddress).Return(uint64(0), nil).Once() + ethClient.On("NonceAt", mock.Anything, fromAddress, mock.Anything).Return(uint64(0), nil).Once() nonceTracker := txmgr.NewNonceTracker(logger.Test(t), txStore, txmgr.NewEvmTxmClient(ethClient, nil)) eb := NewTestEthBroadcaster(t, txStore, ethClient, ethKeyStore, cfg, evmcfg, &testCheckerFactory{}, false, nonceTracker) @@ -980,7 +980,7 @@ func TestEthBroadcaster_ProcessUnstartedEthTxs_ResumingFromCrash(t *testing.T) { evmcfg := evmtest.NewChainScopedConfig(t, cfg) ethClient := testutils.NewEthClientMockWithDefaultChain(t) - ethClient.On("PendingNonceAt", mock.Anything, fromAddress).Return(uint64(0), nil).Once() + ethClient.On("NonceAt", mock.Anything, fromAddress, mock.Anything).Return(uint64(0), nil).Once() nonceTracker := txmgr.NewNonceTracker(logger.Test(t), txStore, txmgr.NewEvmTxmClient(ethClient, nil)) eb := NewTestEthBroadcaster(t, txStore, ethClient, ethKeyStore, cfg, evmcfg, &testCheckerFactory{}, false, nonceTracker) @@ -1044,7 +1044,7 @@ func TestEthBroadcaster_ProcessUnstartedEthTxs_Errors(t *testing.T) { evmcfg := evmtest.NewChainScopedConfig(t, cfg) ethClient := testutils.NewEthClientMockWithDefaultChain(t) - ethClient.On("PendingNonceAt", mock.Anything, fromAddress).Return(uint64(0), nil).Once() + ethClient.On("NonceAt", mock.Anything, fromAddress, mock.Anything).Return(uint64(0), nil).Once() lggr := logger.Test(t) txmClient := txmgr.NewEvmTxmClient(ethClient, nil) nonceTracker := txmgr.NewNonceTracker(lggr, txStore, txmClient) @@ -1597,7 +1597,7 @@ func TestEthBroadcaster_ProcessUnstartedEthTxs_Errors(t *testing.T) { c.EVM[0].GasEstimator.BumpPercent = ptr[uint16](0) })) localNextNonce := getLocalNextNonce(t, nonceTracker, fromAddress) - ethClient.On("PendingNonceAt", mock.Anything, fromAddress).Return(localNextNonce, nil).Once() + ethClient.On("NonceAt", mock.Anything, fromAddress, mock.Anything).Return(localNextNonce, nil).Once() eb2 := NewTestEthBroadcaster(t, txStore, ethClient, ethKeyStore, cfg, evmcfg2, &testCheckerFactory{}, false, nonceTracker) mustCreateUnstartedTx(t, txStore, fromAddress, toAddress, encodedPayload, gasLimit, value, testutils.FixtureChainID) underpricedError := "transaction underpriced" @@ -1629,7 +1629,7 @@ func TestEthBroadcaster_ProcessUnstartedEthTxs_Errors(t *testing.T) { c.EVM[0].GasEstimator.TipCapDefault = gasTipCapDefault })) localNextNonce := getLocalNextNonce(t, nonceTracker, fromAddress) - ethClient.On("PendingNonceAt", mock.Anything, fromAddress).Return(localNextNonce, nil).Once() + ethClient.On("NonceAt", mock.Anything, fromAddress, mock.Anything).Return(localNextNonce, nil).Once() eb2 := NewTestEthBroadcaster(t, txStore, ethClient, ethKeyStore, cfg, evmcfg2, &testCheckerFactory{}, false, nonceTracker) // Second was underpriced but above minimum @@ -1672,7 +1672,7 @@ func TestEthBroadcaster_ProcessUnstartedEthTxs_GasEstimationError(t *testing.T) config := evmtest.NewChainScopedConfig(t, cfg) ethClient := testutils.NewEthClientMockWithDefaultChain(t) - ethClient.On("PendingNonceAt", mock.Anything, fromAddress).Return(uint64(0), nil).Once() + ethClient.On("NonceAt", mock.Anything, fromAddress, mock.Anything).Return(uint64(0), nil).Once() lggr := logger.Test(t) txmClient := txmgr.NewEvmTxmClient(ethClient, nil) nonceTracker := txmgr.NewNonceTracker(lggr, txStore, txmClient) @@ -1741,7 +1741,7 @@ func TestEthBroadcaster_ProcessUnstartedEthTxs_KeystoreErrors(t *testing.T) { kst := ksmocks.NewEth(t) addresses := []gethCommon.Address{fromAddress} kst.On("EnabledAddressesForChain", mock.Anything, testutils.FixtureChainID).Return(addresses, nil).Once() - ethClient.On("PendingNonceAt", mock.Anything, fromAddress).Return(uint64(0), nil).Once() + ethClient.On("NonceAt", mock.Anything, fromAddress, mock.Anything).Return(uint64(0), nil).Once() lggr := logger.Test(t) nonceTracker := txmgr.NewNonceTracker(lggr, txStore, txmgr.NewEvmTxmClient(ethClient, nil)) eb := NewTestEthBroadcaster(t, txStore, ethClient, kst, cfg, evmcfg, &testCheckerFactory{}, false, nonceTracker) @@ -1829,7 +1829,7 @@ func TestEthBroadcaster_SyncNonce(t *testing.T) { kst := ksmocks.NewEth(t) addresses := []gethCommon.Address{fromAddress} kst.On("EnabledAddressesForChain", mock.Anything, testutils.FixtureChainID).Return(addresses, nil).Once() - ethClient.On("PendingNonceAt", mock.Anything, fromAddress).Return(uint64(0), nil).Once() + ethClient.On("NonceAt", mock.Anything, fromAddress, mock.Anything).Return(uint64(0), nil).Once() txmClient := txmgr.NewEvmTxmClient(ethClient, nil) eb := txmgr.NewEvmBroadcaster(txStore, txmClient, evmTxmCfg, txmgr.NewEvmTxmFeeConfig(ge), evmcfg.EVM().Transactions(), cfg.Database().Listener(), kst, txBuilder, lggr, checkerFactory, false, "") err := eb.Start(ctx) diff --git a/core/chains/evm/txmgr/nonce_tracker.go b/core/chains/evm/txmgr/nonce_tracker.go index 941775b7e85..873f2595dbf 100644 --- a/core/chains/evm/txmgr/nonce_tracker.go +++ b/core/chains/evm/txmgr/nonce_tracker.go @@ -23,6 +23,7 @@ type NonceTrackerTxStore interface { type NonceTrackerClient interface { ConfiguredChainID() *big.Int PendingSequenceAt(context.Context, common.Address) (evmtypes.Nonce, error) + SequenceAt(ctx context.Context, addr common.Address, blockNum *big.Int) (evmtypes.Nonce, error) } type nonceTracker struct { @@ -69,9 +70,13 @@ func (s *nonceTracker) getSequenceForAddr(ctx context.Context, address common.Ad seq++ return seq, nil } - // Look for nonce on-chain if no tx found for address in TxStore or if error occurred - // Returns the nonce that should be used for the next transaction so no need to increment - nonce, err := s.client.PendingSequenceAt(ctx, address) + // Look for nonce on-chain if no tx found for address in TxStore or if error occurred. + // We use the mined transaction count (SequenceAt) to determine the next nonce to use instead of the pending transaction count (PendingSequenceAt). + // This allows the TXM to broadcast and track transactions for nonces starting from the last mined transaction preventing the perpetuation of a potential nonce gap. + // NOTE: Any transactions already in the mempool would be attempted to be overwritten but an older transaction can get included before being overwritten. + // Such could be the case if there was a nonce gap that gets filled unblocking the transactions. + // If that occurs, there could be short term noise in the logs surfacing that a transaction expired without ever getting a receipt. + nonce, err := s.client.SequenceAt(ctx, address, nil) if err == nil { return nonce, nil } diff --git a/core/chains/evm/txmgr/nonce_tracker_test.go b/core/chains/evm/txmgr/nonce_tracker_test.go index c9e3cbd76c3..69f7fe50dd4 100644 --- a/core/chains/evm/txmgr/nonce_tracker_test.go +++ b/core/chains/evm/txmgr/nonce_tracker_test.go @@ -61,8 +61,8 @@ func TestNonceTracker_LoadSequenceMap(t *testing.T) { randNonce1 := testutils.NewRandomPositiveInt64() randNonce2 := testutils.NewRandomPositiveInt64() - client.On("PendingNonceAt", mock.Anything, addr1).Return(uint64(randNonce1), nil).Once() - client.On("PendingNonceAt", mock.Anything, addr2).Return(uint64(randNonce2), nil).Once() + client.On("NonceAt", mock.Anything, addr1, mock.Anything).Return(uint64(randNonce1), nil).Once() //nolint:gosec // Disable G115: randNonce1 always positive + client.On("NonceAt", mock.Anything, addr2, mock.Anything).Return(uint64(randNonce2), nil).Once() //nolint:gosec // Disable G115: randNonce2 always positive nonceTracker.LoadNextSequences(ctx, enabledAddresses) seq, err := nonceTracker.GetNextSequence(ctx, addr1) @@ -205,7 +205,7 @@ func TestNonceTracker_GetNextSequence(t *testing.T) { t.Run("fails to get sequence if address is enabled, doesn't exist in map, and getSequenceForAddr fails", func(t *testing.T) { enabledAddresses := []common.Address{addr} txStore.On("FindLatestSequence", mock.Anything, addr, chainID).Return(types.Nonce(0), errors.New("no rows")).Twice() - client.On("PendingNonceAt", mock.Anything, addr).Return(uint64(0), errors.New("RPC unavailable")).Twice() + client.On("NonceAt", mock.Anything, addr, mock.Anything).Return(uint64(0), errors.New("RPC unavailable")).Twice() nonceTracker.LoadNextSequences(ctx, enabledAddresses) _, err := nonceTracker.GetNextSequence(ctx, addr) @@ -217,7 +217,7 @@ func TestNonceTracker_GetNextSequence(t *testing.T) { txStoreNonce := 4 enabledAddresses := []common.Address{addr} txStore.On("FindLatestSequence", mock.Anything, addr, chainID).Return(types.Nonce(0), errors.New("no rows")).Once() - client.On("PendingNonceAt", mock.Anything, addr).Return(uint64(0), errors.New("RPC unavailable")).Once() + client.On("NonceAt", mock.Anything, addr, mock.Anything).Return(uint64(0), errors.New("RPC unavailable")).Once() nonceTracker.LoadNextSequences(ctx, enabledAddresses) txStore.On("FindLatestSequence", mock.Anything, addr, chainID).Return(types.Nonce(txStoreNonce), nil).Once() @@ -272,8 +272,8 @@ func Test_SetNonceAfterInit(t *testing.T) { addr := common.HexToAddress("0xd5e099c71b797516c10ed0f0d895f429c2781142") enabledAddresses := []common.Address{addr} randNonce := testutils.NewRandomPositiveInt64() - client.On("PendingNonceAt", mock.Anything, addr).Return(uint64(0), errors.New("failed to retrieve nonce at startup")).Once() - client.On("PendingNonceAt", mock.Anything, addr).Return(uint64(randNonce), nil).Once() + client.On("NonceAt", mock.Anything, addr, mock.Anything).Return(uint64(0), errors.New("failed to retrieve nonce at startup")).Once() + client.On("NonceAt", mock.Anything, addr, mock.Anything).Return(uint64(randNonce), nil).Once() //nolint:gosec // Disable G115: randNonce always positive nonceTracker.LoadNextSequences(ctx, enabledAddresses) nonce, err := nonceTracker.GetNextSequence(ctx, addr) diff --git a/core/cmd/eth_keys_commands_test.go b/core/cmd/eth_keys_commands_test.go index 64835c7f28b..3442fee7e4a 100644 --- a/core/cmd/eth_keys_commands_test.go +++ b/core/cmd/eth_keys_commands_test.go @@ -93,7 +93,7 @@ func TestShell_ListETHKeys(t *testing.T) { ethClient := newEthMock(t) ethClient.On("BalanceAt", mock.Anything, mock.Anything, mock.Anything).Return(big.NewInt(42), nil) ethClient.On("LINKBalance", mock.Anything, mock.Anything, mock.Anything).Return(commonassets.NewLinkFromJuels(13), nil) - ethClient.On("PendingNonceAt", mock.Anything, mock.Anything).Return(uint64(0), nil) + ethClient.On("NonceAt", mock.Anything, mock.Anything, mock.Anything).Return(uint64(0), nil).Once() app := startNewApplicationV2(t, func(c *chainlink.Config, s *chainlink.Secrets) { c.EVM[0].Enabled = ptr(true) c.EVM[0].NonceAutoSync = ptr(false) @@ -118,7 +118,7 @@ func TestShell_ListETHKeys_Error(t *testing.T) { ethClient := newEthMock(t) ethClient.On("BalanceAt", mock.Anything, mock.Anything, mock.Anything).Return(nil, errors.New("fake error")) ethClient.On("LINKBalance", mock.Anything, mock.Anything, mock.Anything).Return(nil, errors.New("fake error")) - ethClient.On("PendingNonceAt", mock.Anything, mock.Anything).Return(uint64(0), nil) + ethClient.On("NonceAt", mock.Anything, mock.Anything, mock.Anything).Return(uint64(0), nil).Once() app := startNewApplicationV2(t, func(c *chainlink.Config, s *chainlink.Secrets) { c.EVM[0].Enabled = ptr(true) c.EVM[0].NonceAutoSync = ptr(false) @@ -172,7 +172,7 @@ func TestShell_CreateETHKey(t *testing.T) { ethClient := newEthMock(t) ethClient.On("BalanceAt", mock.Anything, mock.Anything, mock.Anything).Return(big.NewInt(42), nil) ethClient.On("LINKBalance", mock.Anything, mock.Anything, mock.Anything).Return(commonassets.NewLinkFromJuels(42), nil) - ethClient.On("PendingNonceAt", mock.Anything, mock.Anything).Return(uint64(0), nil) + ethClient.On("NonceAt", mock.Anything, mock.Anything, mock.Anything).Return(uint64(0), nil).Once() app := startNewApplicationV2(t, func(c *chainlink.Config, s *chainlink.Secrets) { c.EVM[0].Enabled = ptr(true) @@ -247,7 +247,7 @@ func TestShell_ImportExportETHKey_NoChains(t *testing.T) { ethClient := newEthMock(t) ethClient.On("BalanceAt", mock.Anything, mock.Anything, mock.Anything).Return(big.NewInt(42), nil) ethClient.On("LINKBalance", mock.Anything, mock.Anything, mock.Anything).Return(commonassets.NewLinkFromJuels(42), nil) - ethClient.On("PendingNonceAt", mock.Anything, mock.Anything).Return(uint64(0), nil) + ethClient.On("NonceAt", mock.Anything, mock.Anything, mock.Anything).Return(uint64(0), nil).Once() app := startNewApplicationV2(t, func(c *chainlink.Config, s *chainlink.Secrets) { c.EVM[0].Enabled = ptr(true) c.EVM[0].NonceAutoSync = ptr(false) @@ -351,7 +351,7 @@ func TestShell_ImportExportETHKey_WithChains(t *testing.T) { t.Cleanup(func() { deleteKeyExportFile(t) }) ethClient := newEthMock(t) - ethClient.On("PendingNonceAt", mock.Anything, mock.Anything).Return(uint64(0), nil) + ethClient.On("NonceAt", mock.Anything, mock.Anything, mock.Anything).Return(uint64(0), nil).Once() app := startNewApplicationV2(t, func(c *chainlink.Config, s *chainlink.Secrets) { c.EVM[0].Enabled = ptr(true) c.EVM[0].NonceAutoSync = ptr(false) diff --git a/core/cmd/evm_transaction_commands_test.go b/core/cmd/evm_transaction_commands_test.go index 1b593dccd84..77374418a9d 100644 --- a/core/cmd/evm_transaction_commands_test.go +++ b/core/cmd/evm_transaction_commands_test.go @@ -139,8 +139,7 @@ func TestShell_SendEther_From_Txm(t *testing.T) { ethMock := newEthMockWithTransactionsOnBlocksAssertions(t) ethMock.On("BalanceAt", mock.Anything, key.Address, (*big.Int)(nil)).Return(balance.ToInt(), nil) - ethMock.On("NonceAt", mock.Anything, mock.Anything, mock.Anything).Return(uint64(0), nil).Maybe() - ethMock.On("PendingNonceAt", mock.Anything, fromAddress).Return(uint64(0), nil).Once() + ethMock.On("NonceAt", mock.Anything, mock.Anything, mock.Anything).Return(uint64(0), nil) app := startNewApplicationV2(t, func(c *chainlink.Config, s *chainlink.Secrets) { c.EVM[0].Enabled = ptr(true) @@ -203,8 +202,7 @@ func TestShell_SendEther_From_Txm_WEI(t *testing.T) { ethMock := newEthMockWithTransactionsOnBlocksAssertions(t) ethMock.On("BalanceAt", mock.Anything, key.Address, (*big.Int)(nil)).Return(balance.ToInt(), nil) - ethMock.On("NonceAt", mock.Anything, mock.Anything, mock.Anything).Return(uint64(0), nil).Maybe() - ethMock.On("PendingNonceAt", mock.Anything, fromAddress).Return(uint64(0), nil).Once() + ethMock.On("NonceAt", mock.Anything, mock.Anything, mock.Anything).Return(uint64(0), nil) app := startNewApplicationV2(t, func(c *chainlink.Config, s *chainlink.Secrets) { c.EVM[0].Enabled = ptr(true) diff --git a/core/web/eth_keys_controller_test.go b/core/web/eth_keys_controller_test.go index 9cb6a27b434..78982e2e304 100644 --- a/core/web/eth_keys_controller_test.go +++ b/core/web/eth_keys_controller_test.go @@ -33,7 +33,7 @@ func TestETHKeysController_Index_Success(t *testing.T) { ctx := testutils.Context(t) ethClient := cltest.NewEthMocksWithStartupAssertions(t) - ethClient.On("PendingNonceAt", mock.Anything, mock.Anything).Return(uint64(0), nil) + ethClient.On("NonceAt", mock.Anything, mock.Anything, mock.Anything).Return(uint64(0), nil).Once() cfg := configtest.NewGeneralConfig(t, func(c *chainlink.Config, s *chainlink.Secrets) { c.EVM[0].NonceAutoSync = ptr(false) c.EVM[0].BalanceMonitor.Enabled = ptr(false) @@ -85,7 +85,7 @@ func TestETHKeysController_Index_Errors(t *testing.T) { ctx := testutils.Context(t) ethClient := cltest.NewEthMocksWithStartupAssertions(t) - ethClient.On("PendingNonceAt", mock.Anything, mock.Anything).Return(uint64(0), nil) + ethClient.On("NonceAt", mock.Anything, mock.Anything, mock.Anything).Return(uint64(0), nil).Once() cfg := configtest.NewGeneralConfig(t, func(c *chainlink.Config, s *chainlink.Secrets) { c.EVM[0].NonceAutoSync = ptr(false) c.EVM[0].BalanceMonitor.Enabled = ptr(false) @@ -158,7 +158,7 @@ func TestETHKeysController_Index_NotDev(t *testing.T) { t.Parallel() ethClient := cltest.NewEthMocksWithStartupAssertions(t) - ethClient.On("PendingNonceAt", mock.Anything, mock.Anything).Return(uint64(0), nil) + ethClient.On("NonceAt", mock.Anything, mock.Anything, mock.Anything).Return(uint64(0), nil).Once() cfg := configtest.NewGeneralConfig(t, func(c *chainlink.Config, s *chainlink.Secrets) { c.EVM[0].NonceAutoSync = ptr(false) c.EVM[0].BalanceMonitor.Enabled = ptr(false) @@ -227,6 +227,7 @@ func TestETHKeysController_CreateSuccess(t *testing.T) { ethClient.On("BalanceAt", mock.Anything, mock.Anything, mock.Anything).Return(ethBalanceInt, nil) linkBalance := assets.NewLinkFromJuels(42) ethClient.On("LINKBalance", mock.Anything, mock.Anything, mock.Anything).Return(linkBalance, nil) + ethClient.On("NonceAt", mock.Anything, mock.Anything, mock.Anything).Return(uint64(0), nil).Once() client := app.NewHTTPClient(nil) @@ -257,7 +258,7 @@ func TestETHKeysController_ChainSuccess_UpdateNonce(t *testing.T) { ctx := testutils.Context(t) ethClient := cltest.NewEthMocksWithStartupAssertions(t) - ethClient.On("PendingNonceAt", mock.Anything, mock.Anything).Return(uint64(0), nil) + ethClient.On("NonceAt", mock.Anything, mock.Anything, mock.Anything).Return(uint64(0), nil).Once() cfg := configtest.NewGeneralConfig(t, func(c *chainlink.Config, s *chainlink.Secrets) { c.EVM[0].NonceAutoSync = ptr(false) c.EVM[0].BalanceMonitor.Enabled = ptr(false) @@ -300,7 +301,7 @@ func TestETHKeysController_ChainSuccess_Disable(t *testing.T) { ctx := testutils.Context(t) ethClient := cltest.NewEthMocksWithStartupAssertions(t) - ethClient.On("PendingNonceAt", mock.Anything, mock.Anything).Return(uint64(0), nil) + ethClient.On("NonceAt", mock.Anything, mock.Anything, mock.Anything).Return(uint64(0), nil).Once() cfg := configtest.NewGeneralConfig(t, func(c *chainlink.Config, s *chainlink.Secrets) { c.EVM[0].NonceAutoSync = ptr(false) c.EVM[0].BalanceMonitor.Enabled = ptr(false) @@ -391,7 +392,7 @@ func TestETHKeysController_ChainSuccess_ResetWithAbandon(t *testing.T) { ctx := testutils.Context(t) ethClient := cltest.NewEthMocksWithStartupAssertions(t) - ethClient.On("PendingNonceAt", mock.Anything, mock.Anything).Return(uint64(0), nil) + ethClient.On("NonceAt", mock.Anything, mock.Anything, mock.Anything).Return(uint64(0), nil).Once() cfg := configtest.NewGeneralConfig(t, func(c *chainlink.Config, s *chainlink.Secrets) { c.EVM[0].NonceAutoSync = ptr(false) c.EVM[0].BalanceMonitor.Enabled = ptr(false) @@ -464,7 +465,7 @@ func TestETHKeysController_ChainFailure_InvalidAbandon(t *testing.T) { ctx := testutils.Context(t) ethClient := cltest.NewEthMocksWithStartupAssertions(t) - ethClient.On("PendingNonceAt", mock.Anything, mock.Anything).Return(uint64(0), nil) + ethClient.On("NonceAt", mock.Anything, mock.Anything, mock.Anything).Return(uint64(0), nil).Once() cfg := configtest.NewGeneralConfig(t, func(c *chainlink.Config, s *chainlink.Secrets) { c.EVM[0].NonceAutoSync = ptr(false) c.EVM[0].BalanceMonitor.Enabled = ptr(false) @@ -498,7 +499,7 @@ func TestETHKeysController_ChainFailure_InvalidEnabled(t *testing.T) { ctx := testutils.Context(t) ethClient := cltest.NewEthMocksWithStartupAssertions(t) - ethClient.On("PendingNonceAt", mock.Anything, mock.Anything).Return(uint64(0), nil) + ethClient.On("NonceAt", mock.Anything, mock.Anything, mock.Anything).Return(uint64(0), nil).Once() cfg := configtest.NewGeneralConfig(t, func(c *chainlink.Config, s *chainlink.Secrets) { c.EVM[0].NonceAutoSync = ptr(false) c.EVM[0].BalanceMonitor.Enabled = ptr(false) @@ -619,7 +620,7 @@ func TestETHKeysController_ChainFailure_MissingChainID(t *testing.T) { ctx := testutils.Context(t) ethClient := cltest.NewEthMocksWithStartupAssertions(t) - ethClient.On("PendingNonceAt", mock.Anything, mock.Anything).Return(uint64(0), nil) + ethClient.On("NonceAt", mock.Anything, mock.Anything, mock.Anything).Return(uint64(0), nil).Once() cfg := configtest.NewGeneralConfig(t, func(c *chainlink.Config, s *chainlink.Secrets) { c.EVM[0].NonceAutoSync = ptr(false) c.EVM[0].BalanceMonitor.Enabled = ptr(false) @@ -651,7 +652,7 @@ func TestETHKeysController_DeleteSuccess(t *testing.T) { t.Parallel() ctx := testutils.Context(t) ethClient := cltest.NewEthMocksWithStartupAssertions(t) - ethClient.On("PendingNonceAt", mock.Anything, mock.Anything).Return(uint64(0), nil) + ethClient.On("NonceAt", mock.Anything, mock.Anything, mock.Anything).Return(uint64(0), nil).Twice() cfg := configtest.NewGeneralConfig(t, func(c *chainlink.Config, s *chainlink.Secrets) { c.EVM[0].NonceAutoSync = ptr(false) c.EVM[0].BalanceMonitor.Enabled = ptr(false) diff --git a/core/web/evm_transfer_controller_test.go b/core/web/evm_transfer_controller_test.go index 61226839401..55a55399405 100644 --- a/core/web/evm_transfer_controller_test.go +++ b/core/web/evm_transfer_controller_test.go @@ -41,8 +41,9 @@ func TestTransfersController_CreateSuccess_From(t *testing.T) { balance, err := assets.NewEthValueS("200") require.NoError(t, err) - ethClient.On("PendingNonceAt", mock.Anything, key.Address).Return(uint64(1), nil) + ethClient.On("PendingNonceAt", mock.Anything, key.Address).Return(uint64(1), nil).Maybe() ethClient.On("BalanceAt", mock.Anything, key.Address, (*big.Int)(nil)).Return(balance.ToInt(), nil) + ethClient.On("NonceAt", mock.Anything, mock.Anything, mock.Anything).Return(uint64(0), nil).Once() app := cltest.NewApplicationWithKey(t, ethClient, key) require.NoError(t, app.Start(testutils.Context(t))) @@ -83,8 +84,9 @@ func TestTransfersController_CreateSuccess_From_WEI(t *testing.T) { balance, err := assets.NewEthValueS("2") require.NoError(t, err) - ethClient.On("PendingNonceAt", mock.Anything, key.Address).Return(uint64(1), nil) + ethClient.On("PendingNonceAt", mock.Anything, key.Address).Return(uint64(1), nil).Maybe() ethClient.On("BalanceAt", mock.Anything, key.Address, (*big.Int)(nil)).Return(balance.ToInt(), nil) + ethClient.On("NonceAt", mock.Anything, mock.Anything, mock.Anything).Return(uint64(0), nil).Once() app := cltest.NewApplicationWithKey(t, ethClient, key) require.NoError(t, app.Start(testutils.Context(t))) @@ -124,8 +126,9 @@ func TestTransfersController_CreateSuccess_From_BalanceMonitorDisabled(t *testin balance, err := assets.NewEthValueS("200") require.NoError(t, err) - ethClient.On("PendingNonceAt", mock.Anything, key.Address).Return(uint64(1), nil) + ethClient.On("PendingNonceAt", mock.Anything, key.Address).Return(uint64(1), nil).Maybe() ethClient.On("BalanceAt", mock.Anything, key.Address, (*big.Int)(nil)).Return(balance.ToInt(), nil) + ethClient.On("NonceAt", mock.Anything, mock.Anything, mock.Anything).Return(uint64(0), nil).Once() config := configtest.NewGeneralConfig(t, func(c *chainlink.Config, s *chainlink.Secrets) { c.EVM[0].BalanceMonitor.Enabled = ptr(false) @@ -193,8 +196,9 @@ func TestTransfersController_TransferBalanceToLowError(t *testing.T) { ethClient := cltest.NewEthMocksWithTransactionsOnBlocksAssertions(t) - ethClient.On("PendingNonceAt", mock.Anything, key.Address).Return(uint64(1), nil) + ethClient.On("PendingNonceAt", mock.Anything, key.Address).Return(uint64(1), nil).Maybe() ethClient.On("BalanceAt", mock.Anything, key.Address, (*big.Int)(nil)).Return(assets.NewEth(10).ToInt(), nil) + ethClient.On("NonceAt", mock.Anything, mock.Anything, mock.Anything).Return(uint64(0), nil).Once() app := cltest.NewApplicationWithKey(t, ethClient, key) require.NoError(t, app.Start(testutils.Context(t))) @@ -231,8 +235,9 @@ func TestTransfersController_TransferBalanceToLowError_ZeroBalance(t *testing.T) balance, err := assets.NewEthValueS("0") require.NoError(t, err) - ethClient.On("PendingNonceAt", mock.Anything, key.Address).Return(uint64(1), nil) + ethClient.On("PendingNonceAt", mock.Anything, key.Address).Return(uint64(1), nil).Maybe() ethClient.On("BalanceAt", mock.Anything, key.Address, (*big.Int)(nil)).Return(balance.ToInt(), nil) + ethClient.On("NonceAt", mock.Anything, mock.Anything, mock.Anything).Return(uint64(0), nil).Once() app := cltest.NewApplicationWithKey(t, ethClient, key) require.NoError(t, app.Start(testutils.Context(t))) @@ -285,7 +290,7 @@ func TestTransfersController_CreateSuccess_eip1559(t *testing.T) { ethClient.On("PendingNonceAt", mock.Anything, key.Address).Return(uint64(1), nil) ethClient.On("BalanceAt", mock.Anything, key.Address, (*big.Int)(nil)).Return(balance.ToInt(), nil) - ethClient.On("NonceAt", mock.Anything, mock.Anything, mock.Anything).Return(uint64(0), nil).Maybe() + ethClient.On("NonceAt", mock.Anything, mock.Anything, mock.Anything).Return(uint64(0), nil) config := configtest.NewGeneralConfig(t, func(c *chainlink.Config, s *chainlink.Secrets) { c.EVM[0].GasEstimator.EIP1559DynamicFees = ptr(true) diff --git a/core/web/jobs_controller_test.go b/core/web/jobs_controller_test.go index 60abe61537f..f0c8f4b76e7 100644 --- a/core/web/jobs_controller_test.go +++ b/core/web/jobs_controller_test.go @@ -801,6 +801,7 @@ func setupJobsControllerTests(t *testing.T) (ta *cltest.TestApplication, cc clte func setupEthClientForControllerTests(t *testing.T) *evmclimocks.Client { ec := cltest.NewEthMocksWithStartupAssertions(t) ec.On("PendingNonceAt", mock.Anything, mock.Anything).Return(uint64(0), nil).Maybe() + ec.On("NonceAt", mock.Anything, mock.Anything, mock.Anything).Return(uint64(0), nil).Once() ec.On("LatestBlockHeight", mock.Anything).Return(big.NewInt(100), nil).Maybe() ec.On("BalanceAt", mock.Anything, mock.Anything, mock.Anything).Once().Return(big.NewInt(0), nil).Maybe() return ec diff --git a/core/web/pipeline_runs_controller_test.go b/core/web/pipeline_runs_controller_test.go index e123df2bdb3..738d17de600 100644 --- a/core/web/pipeline_runs_controller_test.go +++ b/core/web/pipeline_runs_controller_test.go @@ -254,7 +254,7 @@ func setupPipelineRunsControllerTests(t *testing.T) (cltest.HTTPClientCleaner, i t.Parallel() ctx := testutils.Context(t) ethClient := cltest.NewEthMocksWithStartupAssertions(t) - ethClient.On("PendingNonceAt", mock.Anything, mock.Anything).Return(uint64(0), nil) + ethClient.On("NonceAt", mock.Anything, mock.Anything, mock.Anything).Return(uint64(0), nil).Once() cfg := configtest.NewGeneralConfig(t, func(c *chainlink.Config, s *chainlink.Secrets) { c.OCR.Enabled = ptr(true) c.P2P.V2.Enabled = ptr(true)