Skip to content

Commit 7d5038e

Browse files
authored
perf: remove some more unnecessary RPC calls (#12338)
1 parent 676ec94 commit 7d5038e

File tree

6 files changed

+54
-42
lines changed

6 files changed

+54
-42
lines changed

crates/cast/src/cmd/call.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -357,7 +357,7 @@ impl CallArgs {
357357
),
358358
};
359359

360-
let contracts_bytecode = fetch_contracts_bytecode_from_trace(&provider, &trace).await?;
360+
let contracts_bytecode = fetch_contracts_bytecode_from_trace(&executor, &trace)?;
361361
handle_traces(
362362
trace,
363363
&config,

crates/cast/src/cmd/run.rs

Lines changed: 31 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,11 @@
1-
use crate::debug::handle_traces;
1+
use crate::{debug::handle_traces, utils::apply_chain_and_block_specific_env_changes};
22
use alloy_consensus::Transaction;
33
use alloy_network::{AnyNetwork, TransactionResponse};
44
use alloy_primitives::{
55
Address, Bytes, U256,
6-
map::{HashMap, HashSet},
6+
map::{AddressSet, HashMap},
77
};
8-
use alloy_provider::{Provider, RootProvider};
8+
use alloy_provider::Provider;
99
use alloy_rpc_types::BlockTransactions;
1010
use clap::Parser;
1111
use eyre::{Result, WrapErr};
@@ -25,13 +25,13 @@ use foundry_config::{
2525
use foundry_evm::{
2626
Env,
2727
core::env::AsEnvMut,
28-
executors::{EvmError, TracingExecutor},
28+
executors::{EvmError, Executor, TracingExecutor},
2929
opts::EvmOpts,
3030
traces::{InternalTraceMode, TraceMode, Traces},
3131
utils::configure_tx_env,
3232
};
33-
34-
use crate::utils::apply_chain_and_block_specific_env_changes;
33+
use futures::TryFutureExt;
34+
use revm::DatabaseRef;
3535

3636
/// CLI arguments for `cast run`.
3737
#[derive(Clone, Debug, Parser)]
@@ -151,15 +151,16 @@ impl RunArgs {
151151
let tx_block_number =
152152
tx.block_number.ok_or_else(|| eyre::eyre!("tx may still be pending: {:?}", tx_hash))?;
153153

154-
// fetch the block the transaction was mined in
155-
let block = provider.get_block(tx_block_number.into()).full().await?;
156-
157154
// we need to fork off the parent block
158155
config.fork_block_number = Some(tx_block_number - 1);
159156

160157
let create2_deployer = evm_opts.create2_deployer;
161-
let (mut env, fork, chain, networks) =
162-
TracingExecutor::get_fork_material(&mut config, evm_opts).await?;
158+
let (block, (mut env, fork, chain, networks)) = tokio::try_join!(
159+
// fetch the block the transaction was mined in
160+
provider.get_block(tx_block_number.into()).full().into_future().map_err(Into::into),
161+
TracingExecutor::get_fork_material(&mut config, evm_opts)
162+
)?;
163+
163164
let mut evm_version = self.evm_version;
164165

165166
env.evm_env.cfg_env.disable_block_gas_limit = self.disable_block_gas_limit;
@@ -303,7 +304,7 @@ impl RunArgs {
303304
}
304305
};
305306

306-
let contracts_bytecode = fetch_contracts_bytecode_from_trace(&provider, &result).await?;
307+
let contracts_bytecode = fetch_contracts_bytecode_from_trace(&executor, &result)?;
307308
handle_traces(
308309
result,
309310
&config,
@@ -321,34 +322,32 @@ impl RunArgs {
321322
}
322323
}
323324

324-
pub async fn fetch_contracts_bytecode_from_trace(
325-
provider: &RootProvider<AnyNetwork>,
325+
pub fn fetch_contracts_bytecode_from_trace(
326+
executor: &Executor,
326327
result: &TraceResult,
327328
) -> Result<HashMap<Address, Bytes>> {
328329
let mut contracts_bytecode = HashMap::default();
329330
if let Some(ref traces) = result.traces {
330-
let addresses = gather_trace_addresses(traces);
331-
let results = futures::future::join_all(addresses.into_iter().map(async |a| {
332-
(
333-
a,
334-
provider.get_code_at(a).await.unwrap_or_else(|e| {
335-
sh_warn!("Failed to fetch code for {a:?}: {e:?}").ok();
336-
Bytes::new()
337-
}),
338-
)
339-
}))
340-
.await;
341-
for (address, code) in results {
342-
if !code.is_empty() {
343-
contracts_bytecode.insert(address, code);
331+
contracts_bytecode.extend(gather_trace_addresses(traces).filter_map(|addr| {
332+
// All relevant bytecodes should already be cached in the executor.
333+
let code = executor
334+
.backend()
335+
.basic_ref(addr)
336+
.inspect_err(|e| _ = sh_warn!("Failed to fetch code for {addr}: {e}"))
337+
.ok()??
338+
.code?
339+
.bytes();
340+
if code.is_empty() {
341+
return None;
344342
}
345-
}
343+
Some((addr, code))
344+
}));
346345
}
347346
Ok(contracts_bytecode)
348347
}
349348

350-
fn gather_trace_addresses(traces: &Traces) -> HashSet<Address> {
351-
let mut addresses = HashSet::default();
349+
fn gather_trace_addresses(traces: &Traces) -> impl Iterator<Item = Address> {
350+
let mut addresses = AddressSet::default();
352351
for (_, trace) in traces {
353352
for node in trace.arena.nodes() {
354353
if !node.trace.address.is_zero() {
@@ -359,7 +358,7 @@ fn gather_trace_addresses(traces: &Traces) -> HashSet<Address> {
359358
}
360359
}
361360
}
362-
addresses
361+
addresses.into_iter()
363362
}
364363

365364
impl figment::Provider for RunArgs {

crates/cast/src/debug.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ use foundry_evm::traces::{
1717
pub(crate) async fn handle_traces(
1818
mut result: TraceResult,
1919
config: &Config,
20-
chain: Option<Chain>,
20+
chain: Chain,
2121
contracts_bytecode: &HashMap<Address, Bytes>,
2222
labels: Vec<String>,
2323
with_local_artifacts: bool,
@@ -56,7 +56,7 @@ pub(crate) async fn handle_traces(
5656
.with_labels(labels.chain(config_labels))
5757
.with_signature_identifier(SignaturesIdentifier::from_config(config)?)
5858
.with_label_disabled(disable_label);
59-
let mut identifier = TraceIdentifiers::new().with_external(config, chain)?;
59+
let mut identifier = TraceIdentifiers::new().with_external(config, Some(chain))?;
6060
if let Some(contracts) = &known_contracts {
6161
builder = builder.with_known_contracts(contracts);
6262
identifier = identifier.with_local_and_bytecodes(contracts, contracts_bytecode);

crates/evm/core/src/fork/init.rs

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,17 @@ pub async fn environment<N: Network, P: Provider<N>>(
2121
enable_tx_gas_limit: bool,
2222
configs: NetworkConfigs,
2323
) -> eyre::Result<(Env, N::BlockResponse)> {
24+
trace!(
25+
%memory_limit,
26+
?override_gas_price,
27+
?override_chain_id,
28+
?pin_block,
29+
%origin,
30+
%disable_block_gas_limit,
31+
%enable_tx_gas_limit,
32+
?configs,
33+
"creating fork environment"
34+
);
2435
let bn = match pin_block {
2536
Some(bn) => BlockNumberOrTag::Number(bn),
2637
None => BlockNumberOrTag::Latest,

crates/evm/evm/src/executors/trace.rs

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -21,14 +21,14 @@ pub struct TracingExecutor {
2121
impl TracingExecutor {
2222
pub fn new(
2323
env: Env,
24-
fork: Option<CreateFork>,
24+
fork: CreateFork,
2525
version: Option<EvmVersion>,
2626
trace_mode: TraceMode,
2727
networks: NetworkConfigs,
2828
create2_deployer: Address,
2929
state_overrides: Option<StateOverride>,
3030
) -> eyre::Result<Self> {
31-
let db = Backend::spawn(fork)?;
31+
let db = Backend::spawn(Some(fork))?;
3232
// configures a bare version of the evm executor: no cheatcode inspector is enabled,
3333
// tracing will be enabled only for the targeted transaction
3434
let mut executor = ExecutorBuilder::new()
@@ -79,17 +79,18 @@ impl TracingExecutor {
7979
pub async fn get_fork_material(
8080
config: &mut Config,
8181
mut evm_opts: EvmOpts,
82-
) -> eyre::Result<(Env, Option<CreateFork>, Option<Chain>, NetworkConfigs)> {
82+
) -> eyre::Result<(Env, CreateFork, Chain, NetworkConfigs)> {
8383
evm_opts.fork_url = Some(config.get_rpc_url_or_localhost_http()?.into_owned());
8484
evm_opts.fork_block_number = config.fork_block_number;
8585

8686
let env = evm_opts.evm_env().await?;
8787

88-
let fork = evm_opts.get_fork(config, env.clone());
88+
let fork = evm_opts.get_fork(config, env.clone()).unwrap();
8989
let networks = evm_opts.networks.with_chain_id(env.evm_env.cfg_env.chain_id);
9090
config.labels.extend(networks.precompiles_label());
9191

92-
Ok((env, fork, evm_opts.get_remote_chain_id().await, networks))
92+
let chain = env.tx.chain_id.unwrap().into();
93+
Ok((env, fork, chain, networks))
9394
}
9495
}
9596

crates/forge/src/cmd/test/mod.rs

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -509,7 +509,8 @@ impl TestArgs {
509509
return Ok(TestOutcome::new(Some(runner), results, self.allow_failure));
510510
}
511511

512-
let remote_chain_id = runner.evm_opts.get_remote_chain_id().await;
512+
let remote_chain =
513+
if runner.fork.is_some() { runner.env.tx.chain_id.map(Into::into) } else { None };
513514
let known_contracts = runner.known_contracts.clone();
514515

515516
let libraries = runner.libraries.clone();
@@ -529,7 +530,7 @@ impl TestArgs {
529530
// Avoid using external identifiers for gas report as we decode more traces and this will be
530531
// expensive.
531532
if !self.gas_report {
532-
identifier = identifier.with_external(&config, remote_chain_id)?;
533+
identifier = identifier.with_external(&config, remote_chain)?;
533534
}
534535

535536
// Build the trace decoder.

0 commit comments

Comments
 (0)