diff --git a/crates/script/src/progress.rs b/crates/script/src/progress.rs index 314c4d4983f3a..df2d2ba2dae02 100644 --- a/crates/script/src/progress.rs +++ b/crates/script/src/progress.rs @@ -242,7 +242,11 @@ impl ScriptProgress { Ok(TxStatus::Success(receipt)) => { trace!(tx_hash=?tx_hash, "received tx receipt"); - let msg = format_receipt(deployment_sequence.chain.into(), &receipt); + let msg = format_receipt( + deployment_sequence.chain.into(), + &receipt, + Some(deployment_sequence), + ); seq_progress.inner.write().finish_tx_spinner_with_msg(tx_hash, &msg)?; deployment_sequence.remove_pending(receipt.transaction_hash); @@ -255,7 +259,11 @@ impl ScriptProgress { warn!(tx_hash=?tx_hash, "Transaction Failure"); deployment_sequence.remove_pending(receipt.transaction_hash); - let msg = format_receipt(deployment_sequence.chain.into(), &receipt); + let msg = format_receipt( + deployment_sequence.chain.into(), + &receipt, + Some(deployment_sequence), + ); seq_progress.inner.write().finish_tx_spinner_with_msg(tx_hash, &msg)?; errors.push(format!("Transaction Failure: {:?}", receipt.transaction_hash)); diff --git a/crates/script/src/receipts.rs b/crates/script/src/receipts.rs index 169153f996a28..f7e85f7552ebf 100644 --- a/crates/script/src/receipts.rs +++ b/crates/script/src/receipts.rs @@ -3,6 +3,7 @@ use alloy_network::AnyTransactionReceipt; use alloy_primitives::{TxHash, U256, utils::format_units}; use alloy_provider::{PendingTransactionBuilder, PendingTransactionError, Provider, WatchTxError}; use eyre::{Result, eyre}; +use forge_script_sequence::ScriptSequence; use foundry_common::{provider::RetryProvider, retry, retry::RetryError, shell}; use std::time::Duration; @@ -89,34 +90,60 @@ pub async fn check_tx_status( } /// Prints parts of the receipt to stdout -pub fn format_receipt(chain: Chain, receipt: &AnyTransactionReceipt) -> String { +pub fn format_receipt( + chain: Chain, + receipt: &AnyTransactionReceipt, + sequence: Option<&ScriptSequence>, +) -> String { let gas_used = receipt.gas_used; let gas_price = receipt.effective_gas_price; let block_number = receipt.block_number.unwrap_or_default(); let success = receipt.inner.inner.inner.receipt.status.coerce_status(); + // Find matching transaction metadata for function/contract name + let tx_meta = sequence.and_then(|seq| { + seq.transactions.iter().find(|tx| tx.hash == Some(receipt.transaction_hash)) + }); + let function = tx_meta.and_then(|tx| tx.function.as_deref()).filter(|s| !s.is_empty()); + let contract_name = + tx_meta.and_then(|tx| tx.contract_name.as_deref()).filter(|s| !s.is_empty()); + if shell::is_json() { - let _ = sh_println!( - "{}", - serde_json::json!({ - "chain": chain, - "status": if success { - "success" - } else { - "failed" - }, - "tx_hash": receipt.transaction_hash, - "contract_address": receipt.contract_address.map(|addr| addr.to_string()), - "block_number": block_number, - "gas_used": gas_used, - "gas_price": gas_price, - }) - ); + let mut json = serde_json::json!({ + "chain": chain, + "status": if success { + "success" + } else { + "failed" + }, + "tx_hash": receipt.transaction_hash, + "contract_address": receipt.contract_address.map(|addr| addr.to_string()), + "block_number": block_number, + "gas_used": gas_used, + "gas_price": gas_price, + }); + if let Some(func) = function { + json["function"] = func.into(); + } + if let Some(contract) = contract_name { + json["contract_name"] = contract.into(); + } + + let _ = sh_println!("{}", json); String::new() } else { + let function = + if let Some(func) = function { format!("\nFunction: {func}") } else { String::new() }; + + let contract_name = if let Some(contract) = contract_name { + format!("\nContract: {contract}") + } else { + String::new() + }; + format!( - "\n##### {chain}\n{status} Hash: {tx_hash:?}{contract_address}\nBlock: {block_number}\n{gas}\n\n", + "\n##### {chain}\n{status} Hash: {tx_hash:?}{contract_name}{function}{contract_address}\nBlock: {block_number}\n{gas}\n\n", status = if success { "✅ [Success]" } else { "❌ [Failed]" }, tx_hash = receipt.transaction_hash, contract_address = if let Some(addr) = &receipt.contract_address { diff --git a/crates/script/src/transaction.rs b/crates/script/src/transaction.rs index c93d0d7ef38f7..7d8798aef21fb 100644 --- a/crates/script/src/transaction.rs +++ b/crates/script/src/transaction.rs @@ -58,10 +58,12 @@ impl ScriptTransactionBuilder { let function = if let Some(info) = local_contracts.get(&to) { // This CALL is made to a local contract. self.transaction.contract_name = Some(info.name.clone()); - info.abi.functions().find(|function| function.selector() == selector) + // First try the contract's own ABI, fall back to decoder + info.abi + .functions() + .find(|function| function.selector() == selector) + .or_else(|| decoder.functions.get(selector).and_then(|v| v.first())) } else { - // This CALL is made to an external contract; try to decode it from the given - // decoder. decoder.functions.get(selector).and_then(|v| v.first()) };