diff --git a/crates/cli/src/utils/cmd.rs b/crates/cli/src/utils/cmd.rs index 9f811c267737..240a0f08b522 100644 --- a/crates/cli/src/utils/cmd.rs +++ b/crates/cli/src/utils/cmd.rs @@ -22,11 +22,13 @@ use foundry_evm::{ }; use serde_json::Value; use std::{ - collections::{HashMap, HashSet}, fmt::Write, path::{Path, PathBuf}, str::FromStr + collections::{HashMap, HashSet}, + fmt::Write, + path::{Path, PathBuf}, + str::FromStr, }; use yansi::Paint; - /// Given a `Project`'s output, removes the matching ABI, Bytecode and /// Runtime Bytecode of the given contract. #[track_caller] @@ -375,24 +377,23 @@ pub async fn handle_traces( .build(); let mut addresses: HashSet
= HashSet::new(); - // get all addresses that include in the tx - for (_, trace) in result.traces.as_deref_mut().unwrap_or_default() { + // get all addresses that include in the tx + for (_, trace) in result.traces.as_deref_mut().unwrap_or_default() { for (address, _) in decoder.trace_addresses(trace) { addresses.insert(*address); } } + // lable ronin addresses - let ronin_labels = get_ronin_labels(addresses).await?; + let ronin_labels = get_ronin_labels(chain, addresses).await?; decoder.labels.extend(ronin_labels); - let mut etherscan_identifier = EtherscanIdentifier::new(config, chain)?; if let Some(etherscan_identifier) = &mut etherscan_identifier { for (_, trace) in result.traces.as_deref_mut().unwrap_or_default() { decoder.identify(trace, etherscan_identifier); } } - if decode_internal { let sources = if let Some(etherscan_identifier) = ðerscan_identifier { @@ -402,34 +403,20 @@ pub async fn handle_traces( }; decoder.debug_identifier = Some(DebugTraceIdentifier::new(sources)); } - let mut trace_str = String::new(); - if debug { - let sources = if let Some(etherscan_identifier) = etherscan_identifier { - etherscan_identifier.get_compiled_contracts().await? - } else { - Default::default() - }; - let mut debugger = Debugger::builder() - .traces(result.traces.expect("missing traces")) - .decoder(&decoder) - .sources(sources) - .build(); - debugger.try_run()?; - } else { - trace_str = print_traces(&mut result, &decoder).await?; - } + + let trace_str = print_traces(&mut result, &decoder).await?; Ok(trace_str) } pub async fn print_traces(result: &mut TraceResult, decoder: &CallTraceDecoder) -> Result { let traces = result.traces.as_mut().expect("No traces found"); - let mut trace_str = String::new(); + let mut trace_str: String = String::new(); println!("Traces:"); for (_, arena) in traces { decode_trace_arena(arena, decoder).await?; - trace_str = render_trace_arena(arena); - println!("{}", trace_str); + trace_str.push_str("\n"); + trace_str.push_str(&render_trace_arena(arena)); } println!(); @@ -443,19 +430,37 @@ pub async fn print_traces(result: &mut TraceResult, decoder: &CallTraceDecoder) Ok(trace_str) } -pub async fn get_ronin_labels(addresses: HashSet
) -> Result> { +pub async fn get_ronin_labels( + chain: Option, + addresses: HashSet
, +) -> Result> { let client = reqwest::Client::new(); - let url = "https://explorer-kintsugi.roninchain.com/v2/2020/address"; + + let chain_id = match chain { + Some(chain) => { + if chain.id() == 2020 || chain.id() == 2021 { + chain.id() + } else { + 2020 + } + } + None => 2020, + }; + + let url = format!("https://explorer-kintsugi.roninchain.com/v2/{}/address", chain_id); let response = client.get(url).send().await?.json::().await?; let mut result: HashMap = HashMap::new(); - if let Some(items) = response["result"]["items"].as_object() { for (address_str, item) in items { - if let (address, Some(name)) = (address_str.parse::
().unwrap(), item["name"].as_str()) { + if let (address, Some(name)) = + (address_str.parse::
().unwrap(), item["name"].as_str()) + { if addresses.contains(&address) { result.insert(address, format!("{}", name)); + } else { + result.insert(address, format!("{}", address)); } } } @@ -463,4 +468,3 @@ pub async fn get_ronin_labels(addresses: HashSet
) -> Result &'static ChainInfo { + static CHAIN_INFO: Lazy> = Lazy::new(|| { + let mut m = HashMap::new(); + m.insert( + ChainId::RoninMainnet, + ChainInfo { + name: "Ronin Mainnet", + rpc_url: "https://api-archived.roninchain.com/rpc", + }, + ); + m.insert( + ChainId::RoninTestnet, + ChainInfo { + name: "Ronin Testnet", + rpc_url: "https://saigon-archive.roninchain.com/rpc", + }, + ); + // Add more chains as needed + m + }); + + CHAIN_INFO.get(self).unwrap() + } + + pub fn from_id(id: u64) -> Option { + match id { + 2020 => Some(ChainId::RoninMainnet), + 2021 => Some(ChainId::RoninTestnet), + // Add more matches as needed + _ => None, + } + } +} diff --git a/server/src/cmd/mod.rs b/server/src/cmd/mod.rs index a1f1444ababe..5f322c81ee58 100644 --- a/server/src/cmd/mod.rs +++ b/server/src/cmd/mod.rs @@ -1 +1,2 @@ -pub mod run; \ No newline at end of file +pub mod run; +pub mod chain; \ No newline at end of file diff --git a/server/src/cmd/run.rs b/server/src/cmd/run.rs index 58159e6a7acb..cb53f25b3fef 100644 --- a/server/src/cmd/run.rs +++ b/server/src/cmd/run.rs @@ -78,16 +78,23 @@ pub struct RunArgs { } impl RunArgs { - pub const fn new(rpc_url: String, tx_hash: String) -> Self { - let rpc_opts = RpcOpts { - url: Some(rpc_url), - flashbots: false, - jwt_secret: None, - }; + let rpc_opts = RpcOpts { url: Some(rpc_url), flashbots: false, jwt_secret: None }; let evm_version = Some(EvmVersion::Istanbul); - Self {tx_hash: tx_hash, debug: false, trace_printer: false, quick: false, verbose: false, label: Vec::new(),decode_internal: false ,compute_units_per_second: Some(330), rpc:rpc_opts, evm_version: evm_version, no_rate_limit: true } + Self { + tx_hash, + debug: false, + trace_printer: false, + quick: false, + verbose: false, + label: Vec::new(), + decode_internal: false, + compute_units_per_second: Some(330), + rpc: rpc_opts, + evm_version, + no_rate_limit: true, + } } /// Executes the transaction by replaying it /// @@ -103,7 +110,12 @@ impl RunArgs { let compute_units_per_second = if self.no_rate_limit { Some(u64::MAX) } else { self.compute_units_per_second }; - let provider: alloy_provider::RootProvider, alloy_network::AnyNetwork> = foundry_common::provider::ProviderBuilder::new( + let provider: alloy_provider::RootProvider< + alloy_transport::layers::RetryBackoffService< + foundry_common::provider::runtime_transport::RuntimeTransport, + >, + alloy_network::AnyNetwork, + > = foundry_common::provider::ProviderBuilder::new( &config.get_rpc_url_or_localhost_http()?, ) .compute_units_per_second_opt(compute_units_per_second) @@ -220,7 +232,7 @@ impl RunArgs { } // Execute our transaction - let result = { + let result: TraceResult = { executor.set_trace_printer(self.trace_printer); configure_tx_env(&mut env, &tx); @@ -231,9 +243,10 @@ impl RunArgs { TraceResult::try_from(executor.deploy_with_env(env, None))? } }; - - let trace_str = handle_traces(result, &config, chain, self.label, self.debug, self.decode_internal).await?; + + let trace_str = + handle_traces(result, &config, chain, self.label, self.debug, self.decode_internal) + .await?; Ok(trace_str) - } -} \ No newline at end of file +} diff --git a/server/src/lib.rs b/server/src/lib.rs deleted file mode 100644 index 52958ec91f90..000000000000 --- a/server/src/lib.rs +++ /dev/null @@ -1 +0,0 @@ -pub mod cmd; diff --git a/server/src/main.rs b/server/src/main.rs index 429f69778315..fc8dfad0755b 100644 --- a/server/src/main.rs +++ b/server/src/main.rs @@ -1,22 +1,16 @@ -use actix_web::{get, web, App, HttpResponse, HttpServer, Responder}; -use cmd::run::RunArgs; -use std::thread; -use actix_cors::Cors; -use std::time::Duration; -mod cmd; +pub mod cmd; +use actix_cors::Cors; +use actix_web::{get, web, App, HttpResponse, HttpServer, Responder}; +use cmd::{chain::ChainId, run::RunArgs}; +use std::{thread, time::Duration}; -async fn run_cast_command(tx: web::Path) -> Result { - let args = RunArgs::new( - "https://api-archived.roninchain.com/rpc".to_string(), - tx.as_str().to_string() - ); - +async fn run_cast_command(chain: ChainId, tx: String) -> Result { + let chain_info = chain.info(); + let args: RunArgs = RunArgs::new(chain_info.rpc_url.to_string(), tx); // Run on another thread let handle = thread::spawn(move || { - tokio::runtime::Runtime::new() - .unwrap() - .block_on(async { args.run().await }) + tokio::runtime::Runtime::new().unwrap().block_on(async { args.run().await }) }); let trace_str = handle.join().unwrap(); @@ -27,16 +21,21 @@ async fn run_cast_command(tx: web::Path) -> Result { } } -#[get("/run_cast/{tx}")] -async fn cast_command_handler(tx: web::Path) -> impl Responder { - match run_cast_command(tx).await { - Ok(output) => { - HttpResponse::Ok().content_type("text/plain").body(output) - }, +#[get("/run_cast/{chain_id}/{tx}")] +async fn cast_command_handler(path: web::Path<(u64, String)>) -> impl Responder { + let (chain_id, tx) = path.into_inner(); + + let chain = match ChainId::from_id(chain_id) { + Some(chain) => chain, + None => ChainId::RoninMainnet, + }; + + match run_cast_command(chain, tx).await { + Ok(output) => HttpResponse::Ok().content_type("text/plain").body(output), Err(e) => { println!("Error response: {}", e); HttpResponse::InternalServerError().body(format!("Error executing command: {}", e)) - }, + } } } @@ -51,4 +50,4 @@ async fn main() -> std::io::Result<()> { .workers(5) .run() .await -} \ No newline at end of file +}