From 6f7c1f72f8c3361f1e738296a0ec634c099c8a7c Mon Sep 17 00:00:00 2001 From: pogobounce Date: Mon, 14 Oct 2024 15:32:53 +0300 Subject: [PATCH] fix: running script with `--broadcast` for a transaction sequence can error out due to nonce desync from rpc latency (#9096) * fix for issue #9095 * changed 'if' statement into 'match' * fmt fix * repeat ask for provider nonce on desync * loop break and tokio::time use instead of std::thread --- Cargo.lock | 1 + crates/script/Cargo.toml | 1 + crates/script/src/broadcast.rs | 24 +++++++++++++++++++----- 3 files changed, 21 insertions(+), 5 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index e597a7a91fd0..257f63e31f63 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -3497,6 +3497,7 @@ dependencies = [ "serde", "serde_json", "tempfile", + "tokio", "tracing", "yansi", ] diff --git a/crates/script/Cargo.toml b/crates/script/Cargo.toml index 9c042661775c..37cc13741a7b 100644 --- a/crates/script/Cargo.toml +++ b/crates/script/Cargo.toml @@ -33,6 +33,7 @@ tracing.workspace = true clap = { version = "4", features = ["derive", "env", "unicode", "wrap_help"] } semver.workspace = true futures.workspace = true +tokio.workspace = true async-recursion = "1.0.5" itertools.workspace = true diff --git a/crates/script/src/broadcast.rs b/crates/script/src/broadcast.rs index b0551de57dfa..cb99b26a1d5f 100644 --- a/crates/script/src/broadcast.rs +++ b/crates/script/src/broadcast.rs @@ -26,7 +26,7 @@ use foundry_common::{ use foundry_config::Config; use futures::{future::join_all, StreamExt}; use itertools::Itertools; -use std::sync::Arc; +use std::{cmp::Ordering, sync::Arc}; pub async fn estimate_gas( tx: &mut WithOtherFields, @@ -67,11 +67,25 @@ pub async fn send_transaction( if sequential_broadcast { let from = tx.from.expect("no sender"); - let nonce = provider.get_transaction_count(from).await?; - let tx_nonce = tx.nonce.expect("no nonce"); - if nonce != tx_nonce { - bail!("EOA nonce changed unexpectedly while sending transactions. Expected {tx_nonce} got {nonce} from provider.") + for attempt in 0..5 { + let nonce = provider.get_transaction_count(from).await?; + match nonce.cmp(&tx_nonce) { + Ordering::Greater => { + bail!("EOA nonce changed unexpectedly while sending transactions. Expected {tx_nonce} got {nonce} from provider.") + } + Ordering::Less => { + if attempt == 4 { + bail!("After 5 attempts, provider nonce ({nonce}) is still behind expected nonce ({tx_nonce}).") + } + warn!("Expected nonce ({tx_nonce}) is ahead of provider nonce ({nonce}). Retrying in 1 second..."); + tokio::time::sleep(std::time::Duration::from_millis(1000)).await; + } + Ordering::Equal => { + // Nonces are equal, we can proceed + break; + } + } } }