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
+}