From 9232f69507175f5cbbb3c8cd432ab7200bd54bc7 Mon Sep 17 00:00:00 2001 From: Ragnar Date: Wed, 7 May 2025 17:00:14 +0200 Subject: [PATCH 01/14] Update progress.rs --- crates/script/src/progress.rs | 34 +++++++++++++++++++++++++--------- 1 file changed, 25 insertions(+), 9 deletions(-) diff --git a/crates/script/src/progress.rs b/crates/script/src/progress.rs index a0a5ba5609030..c002e905230ac 100644 --- a/crates/script/src/progress.rs +++ b/crates/script/src/progress.rs @@ -207,20 +207,30 @@ impl ScriptProgress { let mut tasks = futures::stream::iter(futs).buffer_unordered(10); let mut errors: Vec = vec![]; + let mut discarded_transactions = false; while let Some((tx_hash, result)) = tasks.next().await { match result { Err(err) => { - errors.push(format!("Failure on receiving a receipt for {tx_hash:?}:\n{err}")); - - seq_progress.inner.write().finish_tx_spinner(tx_hash); + // Check if the error is about an empty receipt + if err.to_string().contains("Received an empty receipt") { + discarded_transactions = true; + // Special handling for empty receipts - we'll mark these for retrying + deployment_sequence.remove_pending(tx_hash); + let msg = format!("Transaction {tx_hash:?} was discarded by RPC. It will be retried when using --resume."); + seq_progress.inner.write().finish_tx_spinner_with_msg(tx_hash, &msg)?; + } else { + errors.push(format!("Failure on receiving a receipt for {tx_hash:?}:\n{err}")); + seq_progress.inner.write().finish_tx_spinner(tx_hash); + } } Ok(TxStatus::Dropped) => { // We want to remove it from pending so it will be re-broadcast. deployment_sequence.remove_pending(tx_hash); - errors.push(format!("Transaction dropped from the mempool: {tx_hash:?}")); - - seq_progress.inner.write().finish_tx_spinner(tx_hash); + discarded_transactions = true; + + let msg = format!("Transaction {tx_hash:?} dropped from the mempool. It will be retried when using --resume."); + seq_progress.inner.write().finish_tx_spinner_with_msg(tx_hash, &msg)?; } Ok(TxStatus::Success(receipt)) => { trace!(tx_hash=?tx_hash, "received tx receipt"); @@ -249,11 +259,17 @@ impl ScriptProgress { // print any errors if !errors.is_empty() { let mut error_msg = errors.join("\n"); - if !deployment_sequence.pending.is_empty() { - error_msg += "\n\n Add `--resume` to your command to try and continue broadcasting - the transactions." + + // Add information about using --resume if necessary + if !deployment_sequence.pending.is_empty() || discarded_transactions { + error_msg += "\n\n Add `--resume` to your command to try and continue broadcasting "; + error_msg += "the transactions. This will attempt to resend transactions that were discarded by the RPC."; } + eyre::bail!(error_msg); + } else if discarded_transactions { + // If we have discarded transactions but no errors, still inform the user + sh_warn!("Some transactions were discarded by the RPC node. Use `--resume` to retry these transactions.")?; } Ok(()) From 5ba3cdd101e2622f73e3cdb8e191cbefe548b721 Mon Sep 17 00:00:00 2001 From: Ragnar Date: Wed, 7 May 2025 17:00:27 +0200 Subject: [PATCH 02/14] Update receipts.rs --- crates/script/src/receipts.rs | 22 +++++++++++++++++++++- 1 file changed, 21 insertions(+), 1 deletion(-) diff --git a/crates/script/src/receipts.rs b/crates/script/src/receipts.rs index 605cdf9ddb0de..5fd7f88e36993 100644 --- a/crates/script/src/receipts.rs +++ b/crates/script/src/receipts.rs @@ -37,7 +37,27 @@ pub async fn check_tx_status( .get_receipt() .await { - Ok(receipt) => Ok(receipt.into()), + Ok(receipt) => { + // Check if the receipt has valid block information + if receipt.block_number.is_none() || receipt.block_hash.is_none() || receipt.transaction_index.is_none() { + // Receipt is empty, possibly due to RPC discarding the transaction + match provider.get_transaction_by_hash(hash).await { + Ok(_) => { + // Transaction is still known to the node, so we should wait + Err(RetryError::Continue(eyre!( + "Received an empty receipt for {hash}, but transaction is still known to the node, waiting for full receipt" + ))) + } + Err(_) => { + // Transaction is not known to the node, mark it as dropped + Ok(TxStatus::Dropped) + } + } + } else { + // Receipt has valid block information, proceed normally + Ok(receipt.into()) + } + } Err(e) => match provider.get_transaction_by_hash(hash).await { Ok(_) => match e { PendingTransactionError::TxWatcher(WatchTxError::Timeout) => { From cc10e7f4f0aa046ed34ba5909f1af1dbdff09296 Mon Sep 17 00:00:00 2001 From: Ragnar Date: Thu, 8 May 2025 12:18:48 +0200 Subject: [PATCH 03/14] Update receipts.rs --- crates/script/src/receipts.rs | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/crates/script/src/receipts.rs b/crates/script/src/receipts.rs index 5fd7f88e36993..97d2daaee98ba 100644 --- a/crates/script/src/receipts.rs +++ b/crates/script/src/receipts.rs @@ -40,12 +40,14 @@ pub async fn check_tx_status( Ok(receipt) => { // Check if the receipt has valid block information if receipt.block_number.is_none() || receipt.block_hash.is_none() || receipt.transaction_index.is_none() { - // Receipt is empty, possibly due to RPC discarding the transaction + // Receipt is empty, try to sleep and retry a few times match provider.get_transaction_by_hash(hash).await { Ok(_) => { - // Transaction is still known to the node, so we should wait - Err(RetryError::Continue(eyre!( - "Received an empty receipt for {hash}, but transaction is still known to the node, waiting for full receipt" + // Sleep for a short time to allow the transaction to be mined + tokio::time::sleep(Duration::from_millis(500)).await; + // Transaction is still known to the node, retry + Err(RetryError::Retry(eyre!( + "Received an empty receipt for {hash}, but transaction is still known to the node, retrying" ))) } Err(_) => { From e30313aad7301214b7167943020975715bbd82c3 Mon Sep 17 00:00:00 2001 From: Ragnar Date: Thu, 8 May 2025 12:19:03 +0200 Subject: [PATCH 04/14] Update progress.rs --- crates/script/src/progress.rs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/crates/script/src/progress.rs b/crates/script/src/progress.rs index c002e905230ac..01fb12dc0793f 100644 --- a/crates/script/src/progress.rs +++ b/crates/script/src/progress.rs @@ -212,12 +212,12 @@ impl ScriptProgress { while let Some((tx_hash, result)) = tasks.next().await { match result { Err(err) => { - // Check if the error is about an empty receipt + // Check if this is a retry error for empty receipts if err.to_string().contains("Received an empty receipt") { + // We've already retried several times with sleep, but the receipt is still empty discarded_transactions = true; - // Special handling for empty receipts - we'll mark these for retrying deployment_sequence.remove_pending(tx_hash); - let msg = format!("Transaction {tx_hash:?} was discarded by RPC. It will be retried when using --resume."); + let msg = format!("Transaction {tx_hash:?} was discarded by RPC despite multiple retry attempts. It will be retried when using --resume."); seq_progress.inner.write().finish_tx_spinner_with_msg(tx_hash, &msg)?; } else { errors.push(format!("Failure on receiving a receipt for {tx_hash:?}:\n{err}")); From ae67499431c6ac6ed21215a8e5636e2074745143 Mon Sep 17 00:00:00 2001 From: Ragnar Date: Sat, 10 May 2025 11:30:02 +0200 Subject: [PATCH 05/14] Update receipts.rs --- crates/script/src/receipts.rs | 39 ++++++++++++++++++----------------- 1 file changed, 20 insertions(+), 19 deletions(-) diff --git a/crates/script/src/receipts.rs b/crates/script/src/receipts.rs index 97d2daaee98ba..93b9a69052256 100644 --- a/crates/script/src/receipts.rs +++ b/crates/script/src/receipts.rs @@ -38,26 +38,27 @@ pub async fn check_tx_status( .await { Ok(receipt) => { - // Check if the receipt has valid block information - if receipt.block_number.is_none() || receipt.block_hash.is_none() || receipt.transaction_index.is_none() { - // Receipt is empty, try to sleep and retry a few times - match provider.get_transaction_by_hash(hash).await { - Ok(_) => { - // Sleep for a short time to allow the transaction to be mined - tokio::time::sleep(Duration::from_millis(500)).await; - // Transaction is still known to the node, retry - Err(RetryError::Retry(eyre!( - "Received an empty receipt for {hash}, but transaction is still known to the node, retrying" - ))) - } - Err(_) => { - // Transaction is not known to the node, mark it as dropped - Ok(TxStatus::Dropped) - } + // Check if the receipt is pending (missing block information) + let is_pending = receipt.block_number.is_none() || receipt.block_hash.is_none() || receipt.transaction_index.is_none(); + + if !is_pending { + return Ok(receipt.into()); + } + + // Receipt is pending, try to sleep and retry a few times + match provider.get_transaction_by_hash(hash).await { + Ok(_) => { + // Sleep for a short time to allow the transaction to be mined + tokio::time::sleep(Duration::from_millis(500)).await; + // Transaction is still known to the node, retry + Err(RetryError::Retry(eyre!( + "Received a pending receipt for {hash}, but transaction is still known to the node, retrying" + ))) + } + Err(_) => { + // Transaction is not known to the node, mark it as dropped + Ok(TxStatus::Dropped) } - } else { - // Receipt has valid block information, proceed normally - Ok(receipt.into()) } } Err(e) => match provider.get_transaction_by_hash(hash).await { From 31a148f0516d3218af0ac61fd7bed90bf14c7255 Mon Sep 17 00:00:00 2001 From: Ragnar Date: Sat, 10 May 2025 11:30:15 +0200 Subject: [PATCH 06/14] Update progress.rs --- crates/script/src/progress.rs | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/crates/script/src/progress.rs b/crates/script/src/progress.rs index 01fb12dc0793f..08a94ed02c53d 100644 --- a/crates/script/src/progress.rs +++ b/crates/script/src/progress.rs @@ -212,9 +212,9 @@ impl ScriptProgress { while let Some((tx_hash, result)) = tasks.next().await { match result { Err(err) => { - // Check if this is a retry error for empty receipts - if err.to_string().contains("Received an empty receipt") { - // We've already retried several times with sleep, but the receipt is still empty + // Check if this is a retry error for pending receipts + if err.to_string().contains("Received a pending receipt") { + // We've already retried several times with sleep, but the receipt is still pending discarded_transactions = true; deployment_sequence.remove_pending(tx_hash); let msg = format!("Transaction {tx_hash:?} was discarded by RPC despite multiple retry attempts. It will be retried when using --resume."); @@ -262,8 +262,9 @@ impl ScriptProgress { // Add information about using --resume if necessary if !deployment_sequence.pending.is_empty() || discarded_transactions { - error_msg += "\n\n Add `--resume` to your command to try and continue broadcasting "; - error_msg += "the transactions. This will attempt to resend transactions that were discarded by the RPC."; + error_msg += r#" + +Add `--resume` to your command to try and continue broadcasting the transactions. This will attempt to resend transactions that were discarded by the RPC."#; } eyre::bail!(error_msg); From 78b82f876e6ffec2fae10d0ff51d2ba81412c5a8 Mon Sep 17 00:00:00 2001 From: Ragnar Date: Wed, 24 Sep 2025 18:15:28 +0200 Subject: [PATCH 07/14] Update receipts.rs --- crates/script/src/receipts.rs | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/crates/script/src/receipts.rs b/crates/script/src/receipts.rs index fe39c206e87f2..26f4642ff8aea 100644 --- a/crates/script/src/receipts.rs +++ b/crates/script/src/receipts.rs @@ -6,6 +6,13 @@ use eyre::{Result, eyre}; use foundry_common::{provider::RetryProvider, retry, retry::RetryError, shell}; use std::time::Duration; +/// Marker error type for pending receipts +#[derive(Debug, thiserror::Error)] +#[error("Received a pending receipt for {tx_hash}, but transaction is still known to the node, retrying")] +pub struct PendingReceiptError { + pub tx_hash: TxHash, +} + /// Convenience enum for internal signalling of transaction status pub enum TxStatus { Dropped, @@ -51,9 +58,7 @@ pub async fn check_tx_status( // Sleep for a short time to allow the transaction to be mined tokio::time::sleep(Duration::from_millis(500)).await; // Transaction is still known to the node, retry - Err(RetryError::Retry(eyre!( - "Received a pending receipt for {hash}, but transaction is still known to the node, retrying" - ))) + Err(RetryError::Retry(PendingReceiptError { tx_hash: hash }.into())) } Err(_) => { // Transaction is not known to the node, mark it as dropped From 841428c385d4a684dccf9a5fbd1c91838d7b7fd3 Mon Sep 17 00:00:00 2001 From: Ragnar Date: Wed, 24 Sep 2025 18:17:09 +0200 Subject: [PATCH 08/14] Update progress.rs --- crates/script/src/progress.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/crates/script/src/progress.rs b/crates/script/src/progress.rs index 8324787a7d57f..1acb2c7483987 100644 --- a/crates/script/src/progress.rs +++ b/crates/script/src/progress.rs @@ -1,4 +1,4 @@ -use crate::receipts::{TxStatus, check_tx_status, format_receipt}; +use crate::receipts::{TxStatus, PendingReceiptError, check_tx_status, format_receipt}; use alloy_chains::Chain; use alloy_primitives::{ B256, @@ -213,7 +213,7 @@ impl ScriptProgress { match result { Err(err) => { // Check if this is a retry error for pending receipts - if err.to_string().contains("Received a pending receipt") { + if err.downcast_ref::().is_some() { // We've already retried several times with sleep, but the receipt is still pending discarded_transactions = true; deployment_sequence.remove_pending(tx_hash); From da81c74c441a3e0eb0927f6bcf3a1f28fb300ebd Mon Sep 17 00:00:00 2001 From: Ragnar Date: Wed, 24 Sep 2025 18:17:29 +0200 Subject: [PATCH 09/14] Update Cargo.toml --- crates/script/Cargo.toml | 1 + 1 file changed, 1 insertion(+) diff --git a/crates/script/Cargo.toml b/crates/script/Cargo.toml index b3307f6b44ece..1caf15f9c05ed 100644 --- a/crates/script/Cargo.toml +++ b/crates/script/Cargo.toml @@ -54,6 +54,7 @@ alloy-dyn-abi.workspace = true alloy-primitives.workspace = true alloy-eips.workspace = true alloy-consensus.workspace = true +thiserror.workspace = true [dev-dependencies] tempfile.workspace = true From c72c2f8b17637a285369b796870b1e5facfc5e06 Mon Sep 17 00:00:00 2001 From: Ragnar Date: Fri, 26 Sep 2025 17:54:50 +0200 Subject: [PATCH 10/14] Update progress.rs --- crates/script/src/progress.rs | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/crates/script/src/progress.rs b/crates/script/src/progress.rs index 1acb2c7483987..e104e927bc435 100644 --- a/crates/script/src/progress.rs +++ b/crates/script/src/progress.rs @@ -217,8 +217,7 @@ impl ScriptProgress { // We've already retried several times with sleep, but the receipt is still pending discarded_transactions = true; deployment_sequence.remove_pending(tx_hash); - let msg = format!("Transaction {tx_hash:?} was discarded by RPC despite multiple retry attempts. It will be retried when using --resume."); - seq_progress.inner.write().finish_tx_spinner_with_msg(tx_hash, &msg)?; + seq_progress.inner.write().finish_tx_spinner_with_msg(tx_hash, &err.to_string())?; } else { errors.push(format!("Failure on receiving a receipt for {tx_hash:?}:\n{err}")); seq_progress.inner.write().finish_tx_spinner(tx_hash); From 40d141e0dd52ef8d5976faeeade728a866a9d1c5 Mon Sep 17 00:00:00 2001 From: Ragnar Date: Tue, 30 Sep 2025 22:51:13 +0200 Subject: [PATCH 11/14] Update coverage.rs --- crates/forge/src/coverage.rs | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/crates/forge/src/coverage.rs b/crates/forge/src/coverage.rs index 46baeddeda0ae..bb9e749cbcff2 100644 --- a/crates/forge/src/coverage.rs +++ b/crates/forge/src/coverage.rs @@ -166,11 +166,8 @@ impl CoverageReporter for LcovReporter { } } CoverageItemKind::Branch { branch_id, path_id, .. } => { - writeln!( - out, - "BRDA:{line},{branch_id},{path_id},{}", - if hits == 0 { "-" } else { &hits.to_string() } - )?; + let hits_str = if hits == 0 { "-" } else { &hits.to_string() }; + writeln!(out, "BRDA:{line},{branch_id},{path_id},{hits_str}")?; } } } From cc757bc54221d3a875de1e03c041664e2fd5e31f Mon Sep 17 00:00:00 2001 From: Ragnar Date: Tue, 30 Sep 2025 22:51:29 +0200 Subject: [PATCH 12/14] Update vanity.rs --- crates/cast/src/cmd/wallet/vanity.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/crates/cast/src/cmd/wallet/vanity.rs b/crates/cast/src/cmd/wallet/vanity.rs index a0a58c3cd7851..ffcd63be65cc5 100644 --- a/crates/cast/src/cmd/wallet/vanity.rs +++ b/crates/cast/src/cmd/wallet/vanity.rs @@ -149,8 +149,8 @@ impl VanityArgs { "Successfully found vanity address in {:.3} seconds.{}{}\nAddress: {}\nPrivate Key: 0x{}", timer.elapsed().as_secs_f64(), if nonce.is_some() { "\nContract address: " } else { "" }, - if nonce.is_some() { - wallet.address().create(nonce.unwrap()).to_checksum(None) + if let Some(nonce_val) = nonce { + wallet.address().create(nonce_val).to_checksum(None) } else { String::new() }, From b4f5cfc89ed0b4616885791e37159bbdb1a5d996 Mon Sep 17 00:00:00 2001 From: Ragnar Date: Tue, 30 Sep 2025 22:52:10 +0200 Subject: [PATCH 13/14] Update progress.rs --- crates/script/src/progress.rs | 28 +++++++++++++++++++--------- 1 file changed, 19 insertions(+), 9 deletions(-) diff --git a/crates/script/src/progress.rs b/crates/script/src/progress.rs index e104e927bc435..885597b0def71 100644 --- a/crates/script/src/progress.rs +++ b/crates/script/src/progress.rs @@ -1,4 +1,4 @@ -use crate::receipts::{TxStatus, PendingReceiptError, check_tx_status, format_receipt}; +use crate::receipts::{PendingReceiptError, TxStatus, check_tx_status, format_receipt}; use alloy_chains::Chain; use alloy_primitives::{ B256, @@ -214,12 +214,18 @@ impl ScriptProgress { Err(err) => { // Check if this is a retry error for pending receipts if err.downcast_ref::().is_some() { - // We've already retried several times with sleep, but the receipt is still pending + // We've already retried several times with sleep, but the receipt is still + // pending discarded_transactions = true; deployment_sequence.remove_pending(tx_hash); - seq_progress.inner.write().finish_tx_spinner_with_msg(tx_hash, &err.to_string())?; + seq_progress + .inner + .write() + .finish_tx_spinner_with_msg(tx_hash, &err.to_string())?; } else { - errors.push(format!("Failure on receiving a receipt for {tx_hash:?}:\n{err}")); + errors.push(format!( + "Failure on receiving a receipt for {tx_hash:?}:\n{err}" + )); seq_progress.inner.write().finish_tx_spinner(tx_hash); } } @@ -227,8 +233,10 @@ impl ScriptProgress { // We want to remove it from pending so it will be re-broadcast. deployment_sequence.remove_pending(tx_hash); discarded_transactions = true; - - let msg = format!("Transaction {tx_hash:?} dropped from the mempool. It will be retried when using --resume."); + + let msg = format!( + "Transaction {tx_hash:?} dropped from the mempool. It will be retried when using --resume." + ); seq_progress.inner.write().finish_tx_spinner_with_msg(tx_hash, &msg)?; } Ok(TxStatus::Success(receipt)) => { @@ -258,18 +266,20 @@ impl ScriptProgress { // print any errors if !errors.is_empty() { let mut error_msg = errors.join("\n"); - + // Add information about using --resume if necessary if !deployment_sequence.pending.is_empty() || discarded_transactions { error_msg += r#" Add `--resume` to your command to try and continue broadcasting the transactions. This will attempt to resend transactions that were discarded by the RPC."#; } - + eyre::bail!(error_msg); } else if discarded_transactions { // If we have discarded transactions but no errors, still inform the user - sh_warn!("Some transactions were discarded by the RPC node. Use `--resume` to retry these transactions.")?; + sh_warn!( + "Some transactions were discarded by the RPC node. Use `--resume` to retry these transactions." + )?; } Ok(()) From 690370c95a05ef9c6271b59b3e869008a69a8517 Mon Sep 17 00:00:00 2001 From: Ragnar Date: Tue, 30 Sep 2025 22:52:34 +0200 Subject: [PATCH 14/14] Update receipts.rs --- crates/script/src/receipts.rs | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/crates/script/src/receipts.rs b/crates/script/src/receipts.rs index 26f4642ff8aea..169153f996a28 100644 --- a/crates/script/src/receipts.rs +++ b/crates/script/src/receipts.rs @@ -8,7 +8,9 @@ use std::time::Duration; /// Marker error type for pending receipts #[derive(Debug, thiserror::Error)] -#[error("Received a pending receipt for {tx_hash}, but transaction is still known to the node, retrying")] +#[error( + "Received a pending receipt for {tx_hash}, but transaction is still known to the node, retrying" +)] pub struct PendingReceiptError { pub tx_hash: TxHash, } @@ -46,8 +48,10 @@ pub async fn check_tx_status( { Ok(receipt) => { // Check if the receipt is pending (missing block information) - let is_pending = receipt.block_number.is_none() || receipt.block_hash.is_none() || receipt.transaction_index.is_none(); - + let is_pending = receipt.block_number.is_none() + || receipt.block_hash.is_none() + || receipt.transaction_index.is_none(); + if !is_pending { return Ok(receipt.into()); }