diff --git a/crates/cast/bin/cmd/run.rs b/crates/cast/bin/cmd/run.rs index 9d04ed1e2c1f..779b8370a9cf 100644 --- a/crates/cast/bin/cmd/run.rs +++ b/crates/cast/bin/cmd/run.rs @@ -21,7 +21,7 @@ use foundry_config::{ use foundry_evm::{ executors::{EvmError, TracingExecutor}, opts::EvmOpts, - utils::configure_tx_env, + utils::{configure_quorum, configure_tx_env}, }; /// CLI arguments for `cast run`. @@ -109,7 +109,7 @@ impl RunArgs { .build()?; let tx_hash = self.tx_hash.parse().wrap_err("invalid tx hash")?; - let tx = provider + let mut tx = provider .get_transaction_by_hash(tx_hash) .await .wrap_err_with(|| format!("tx not found: {tx_hash:?}"))? @@ -188,10 +188,10 @@ impl RunArgs { tx.transaction_type == Some(SYSTEM_TRANSACTION_TYPE) { pb.set_position((index + 1) as u64); - continue; + continue } if tx.hash == tx_hash { - break; + break } configure_tx_env(&mut env, &tx.inner); @@ -231,6 +231,7 @@ impl RunArgs { let result = { executor.set_trace_printer(self.trace_printer); + configure_quorum(&mut tx, provider).await; configure_tx_env(&mut env, &tx.inner); if let Some(to) = tx.to { diff --git a/crates/evm/core/src/utils.rs b/crates/evm/core/src/utils.rs index bd17aae44292..8e633ee1abe9 100644 --- a/crates/evm/core/src/utils.rs +++ b/crates/evm/core/src/utils.rs @@ -4,12 +4,15 @@ use crate::{ InspectorExt, }; use alloy_json_abi::{Function, JsonAbi}; -use alloy_primitives::{Address, Selector, TxKind, U256}; +use alloy_primitives::{Address, Bytes, Selector, TxKind, Uint, U256}; use alloy_provider::{ - network::{BlockResponse, HeaderResponse}, - Network, + network::{AnyNetwork, BlockResponse, HeaderResponse}, + Network, Provider, RootProvider, }; use alloy_rpc_types::{Transaction, TransactionRequest}; +use alloy_serde::WithOtherFields; +use alloy_transport::layers::RetryBackoffService; +use foundry_common::provider::runtime_transport::RuntimeTransport; use foundry_config::NamedChain; use foundry_fork_db::DatabaseError; use revm::{ @@ -142,6 +145,44 @@ pub fn configure_tx_req_env( Ok(()) } +/// Configures the input to the raw payload for the given RPC transaction if it is a quorum private +/// transaction. +pub async fn configure_quorum( + tx: &mut WithOtherFields, + provider: RootProvider, AnyNetwork>, +) { + if let Some(signature) = tx.inner.signature { + let v = signature.v; + + let is_private_quorum_txn = + (v == Uint::from(37) || v == Uint::from(38)) && tx.input.len() == 64; + + if is_private_quorum_txn { + println!("Private quorum transaction detected."); + + let result: alloy_transport::TransportResult = + provider.client().request("eth_getQuorumPayload", (tx.input.clone(),)).await; + + match result { + Ok(tessera_input) => { + println!( + "Executing private quorum transaction with quorum payload: {:?}", + tessera_input.to_string() + ); + tx.input = tessera_input; + } + Err(e) => { + println!( + "eth_getQuorumPayload threw an error: {e}, cannot fetch transaction + input {:?}", + tx.hash + ); + } + } + } + } +} + /// Get the gas used, accounting for refunds pub fn gas_used(spec: SpecId, spent: u64, refunded: u64) -> u64 { let refund_quotient = if SpecId::enabled(spec, SpecId::LONDON) { 5 } else { 2 };