Skip to content

Commit

Permalink
feat(cast): tx trace in specific chain
Browse files Browse the repository at this point in the history
  • Loading branch information
tringuyenskymavis committed Aug 8, 2024
1 parent 780b248 commit 5692218
Show file tree
Hide file tree
Showing 7 changed files with 135 additions and 69 deletions.
66 changes: 35 additions & 31 deletions crates/cli/src/utils/cmd.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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]
Expand Down Expand Up @@ -375,24 +377,23 @@ pub async fn handle_traces(
.build();

let mut addresses: HashSet<Address> = 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) = &etherscan_identifier {
Expand All @@ -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<String> {
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!();

Expand All @@ -443,24 +430,41 @@ pub async fn print_traces(result: &mut TraceResult, decoder: &CallTraceDecoder)
Ok(trace_str)
}

pub async fn get_ronin_labels(addresses: HashSet<Address>) -> Result<HashMap<Address, String>> {
pub async fn get_ronin_labels(
chain: Option<Chain>,
addresses: HashSet<Address>,
) -> Result<HashMap<Address, String>> {
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::<Value>().await?;
let mut result: HashMap<Address, String> = 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::<Address>().unwrap(), item["name"].as_str()) {
if let (address, Some(name)) =
(address_str.parse::<Address>().unwrap(), item["name"].as_str())
{
if addresses.contains(&address) {
result.insert(address, format!("<span>{}</span>", name));
} else {
result.insert(address, format!("<span>{}</span>", address));
}
}
}
}

Ok(result)
}

1 change: 1 addition & 0 deletions server/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,7 @@ rand.workspace = true
rayon.workspace = true
serde_json.workspace = true
serde.workspace = true
once_cell = "1.8.0"

clap = { version = "4", features = ["derive", "env", "unicode", "wrap_help"] }
clap_complete = "4"
Expand Down
49 changes: 49 additions & 0 deletions server/src/cmd/chain.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
use once_cell::sync::Lazy;
use std::collections::HashMap;

#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub enum ChainId {
RoninMainnet = 2020,
RoninTestnet = 2021,
// Add more chains as needed
}

pub struct ChainInfo {
pub name: &'static str,
pub rpc_url: &'static str,
}

impl ChainId {
pub fn info(&self) -> &'static ChainInfo {
static CHAIN_INFO: Lazy<HashMap<ChainId, ChainInfo>> = 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<Self> {
match id {
2020 => Some(ChainId::RoninMainnet),
2021 => Some(ChainId::RoninTestnet),
// Add more matches as needed
_ => None,
}
}
}
3 changes: 2 additions & 1 deletion server/src/cmd/mod.rs
Original file line number Diff line number Diff line change
@@ -1 +1,2 @@
pub mod run;
pub mod run;
pub mod chain;
39 changes: 26 additions & 13 deletions server/src/cmd/run.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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
///
Expand All @@ -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_transport::layers::RetryBackoffService<foundry_common::provider::runtime_transport::RuntimeTransport>, 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)
Expand Down Expand Up @@ -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);
Expand All @@ -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)

}
}
}
1 change: 0 additions & 1 deletion server/src/lib.rs

This file was deleted.

45 changes: 22 additions & 23 deletions server/src/main.rs
Original file line number Diff line number Diff line change
@@ -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<String>) -> Result<String, String> {
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<String, String> {
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();
Expand All @@ -27,16 +21,21 @@ async fn run_cast_command(tx: web::Path<String>) -> Result<String, String> {
}
}

#[get("/run_cast/{tx}")]
async fn cast_command_handler(tx: web::Path<String>) -> 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))
},
}
}
}

Expand All @@ -51,4 +50,4 @@ async fn main() -> std::io::Result<()> {
.workers(5)
.run()
.await
}
}

0 comments on commit 5692218

Please sign in to comment.