Skip to content
This repository has been archived by the owner on Oct 19, 2024. It is now read-only.

NonceManagerMiddleware failures when running concurrently #2742

Open
fgimenez opened this issue Feb 19, 2024 · 1 comment
Open

NonceManagerMiddleware failures when running concurrently #2742

fgimenez opened this issue Feb 19, 2024 · 1 comment
Labels
bug Something isn't working

Comments

@fgimenez
Copy link

Version
v2.0.11 (https://github.com/gakonst/ethers-rs#40cc8cc5)

Platform
Linux arkham 6.7.4-200.fc39.x86_64 #1 SMP PREEMPT_DYNAMIC Mon Feb 5 22:21:14 UTC 2024 x86_64 GNU/Linux

Description
I'm sending a transaction to a smart contract function using code similar to this:

let tx_receipt = self
    .payments
    .book_service(U256::from_big_endian(&cluster_id.into_bytes()), amounts)
    .send()
    .await?
    .await?
    .unwrap();

self.payments is an instance of the bindings to a smart contract. The provider was created like this:

let provider = Arc::new(Provider::<Http>::try_from(rpc_url)?.with_signer(wallet.clone()).nonce_manager(wallet.address()))

When I run the code to send the transactions in multiple async tasks, I start getting errors like replacement transaction underpriced, which seems to reflect that the nonce was not properly updated.

Any help is very appreciated, thanks!

@fgimenez fgimenez added the bug Something isn't working label Feb 19, 2024
@fgimenez
Copy link
Author

To give more context, I'm running a load test tool that executes the code above to send transactions. The tool spawns multiple clients using the same wallet for all of them.

The first thing I tried to fix the nonce issue was to put a lock around the code that sends the transaction. This completely fixed the problem, but the throughput was very bad.

Next, looking at the NonceManagerMiddleware code, I replaced this https://github.com/gakonst/ethers-rs/blob/master/ethers-middleware/src/nonce_manager.rs#L74-L80 (which AIUI could be problematic with concurrent access) to call instead initialize_nonce and take advantage of mutex guard's lock.

With this in place (and without the lock around my send transaction call), errors are back, but now instead of "replacement transaction underpriced" I get "already known" errors, as I understand it now the same transaction (same tx hash) is found more than once in the mempool? I wonder if this code https://github.com/gakonst/ethers-rs/blob/master/ethers-middleware/src/nonce_manager.rs#L152-L162 could also benefit from a lock for concurrent access?

Let me know if I can give any additional info.

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
bug Something isn't working
Projects
None yet
Development

No branches or pull requests

1 participant