Skip to content

Commit 3aa03f5

Browse files
committed
generic cast run
1 parent 1e342ef commit 3aa03f5

2 files changed

Lines changed: 52 additions & 47 deletions

File tree

crates/cast/src/cmd/run.rs

Lines changed: 40 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -2,10 +2,10 @@ use crate::{
22
debug::handle_traces,
33
utils::{apply_chain_and_block_specific_env_changes, block_env_from_header},
44
};
5-
use alloy_consensus::{BlockHeader, Transaction};
5+
use alloy_consensus::{BlockHeader, Transaction, transaction::SignerRecoverable};
66

77
use alloy_evm::FromRecoveredTx;
8-
use alloy_network::{AnyNetwork, TransactionResponse};
8+
use alloy_network::{BlockResponse, TransactionResponse};
99
use alloy_primitives::{
1010
Address, Bytes, U256,
1111
map::{AddressSet, HashMap},
@@ -18,7 +18,9 @@ use foundry_cli::{
1818
opts::{EtherscanOpts, RpcOpts},
1919
utils::{TraceResult, init_progress},
2020
};
21-
use foundry_common::{SYSTEM_TRANSACTION_TYPE, is_impersonated_tx, is_known_system_sender, shell};
21+
use foundry_common::{
22+
SYSTEM_TRANSACTION_TYPE, is_known_system_sender, provider::ProviderBuilder, shell,
23+
};
2224
use foundry_compilers::artifacts::EvmVersion;
2325
use foundry_config::{
2426
Config,
@@ -28,13 +30,16 @@ use foundry_config::{
2830
},
2931
};
3032
use foundry_evm::{
31-
core::evm::EthEvmNetwork,
33+
core::{
34+
FoundryBlock as _,
35+
evm::{EthEvmNetwork, FoundryEvmNetwork, TempoEvmNetwork, TxEnvFor},
36+
},
3237
executors::{EvmError, Executor, TracingExecutor},
3338
opts::EvmOpts,
3439
traces::{InternalTraceMode, TraceMode, Traces},
3540
};
3641
use futures::TryFutureExt;
37-
use revm::{DatabaseRef, context::TxEnv};
42+
use revm::{DatabaseRef, context::Block};
3843

3944
/// CLI arguments for `cast run`.
4045
#[derive(Clone, Debug, Parser)]
@@ -126,6 +131,16 @@ impl RunArgs {
126131
///
127132
/// Note: This executes the transaction(s) as is: Cheatcodes are disabled
128133
pub async fn run(self) -> Result<()> {
134+
let figment = self.rpc.clone().into_figment(self.with_local_artifacts).merge(&self);
135+
let evm_opts = figment.extract::<EvmOpts>()?;
136+
if evm_opts.networks.is_tempo() {
137+
self.run_with_evm::<TempoEvmNetwork>().await
138+
} else {
139+
self.run_with_evm::<EthEvmNetwork>().await
140+
}
141+
}
142+
143+
async fn run_with_evm<FEN: FoundryEvmNetwork>(self) -> Result<()> {
129144
let figment = self.rpc.clone().into_figment(self.with_local_artifacts).merge(&self);
130145
let evm_opts = figment.extract::<EvmOpts>()?;
131146
let mut config = Config::from_provider(figment)?.sanitized();
@@ -138,7 +153,7 @@ impl RunArgs {
138153
let compute_units_per_second =
139154
if self.no_rate_limit { Some(u64::MAX) } else { self.compute_units_per_second };
140155

141-
let provider = foundry_cli::utils::get_provider_builder(&config)?
156+
let provider = ProviderBuilder::<FEN::Network>::from_config(&config)?
142157
.compute_units_per_second_opt(compute_units_per_second)
143158
.build()?;
144159

@@ -160,8 +175,9 @@ impl RunArgs {
160175
));
161176
}
162177

163-
let tx_block_number =
164-
tx.block_number.ok_or_else(|| eyre::eyre!("tx may still be pending: {:?}", tx_hash))?;
178+
let tx_block_number = tx
179+
.block_number()
180+
.ok_or_else(|| eyre::eyre!("tx may still be pending: {:?}", tx_hash))?;
165181

166182
// we need to fork off the parent block
167183
config.fork_block_number = Some(tx_block_number - 1);
@@ -170,7 +186,7 @@ impl RunArgs {
170186
let (block, (mut evm_env, tx_env, fork, chain, networks)) = tokio::try_join!(
171187
// fetch the block the transaction was mined in
172188
provider.get_block(tx_block_number.into()).full().into_future().map_err(Into::into),
173-
TracingExecutor::<EthEvmNetwork>::get_fork_material(&mut config, evm_opts)
189+
TracingExecutor::<FEN>::get_fork_material(&mut config, evm_opts)
174190
)?;
175191

176192
let mut evm_version = self.evm_version;
@@ -184,20 +200,20 @@ impl RunArgs {
184200
}
185201

186202
evm_env.cfg_env.limit_contract_code_size = None;
187-
evm_env.block_env.number = U256::from(tx_block_number);
203+
evm_env.block_env.set_number(U256::from(tx_block_number));
188204

189205
if let Some(block) = &block {
190-
evm_env.block_env = block_env_from_header(&block.header);
206+
evm_env.block_env = block_env_from_header(block.header());
191207

192208
// TODO: we need a smarter way to map the block to the corresponding evm_version for
193209
// commonly used chains
194210
if evm_version.is_none() {
195211
// if the block has the excess_blob_gas field, we assume it's a Cancun block
196-
if block.header.excess_blob_gas().is_some() {
212+
if block.header().excess_blob_gas().is_some() {
197213
evm_version = Some(EvmVersion::Prague);
198214
}
199215
}
200-
apply_chain_and_block_specific_env_changes::<AnyNetwork, _, _>(
216+
apply_chain_and_block_specific_env_changes::<FEN::Network, _, _>(
201217
&mut evm_env,
202218
block,
203219
config.networks,
@@ -212,7 +228,7 @@ impl RunArgs {
212228
InternalTraceMode::None
213229
})
214230
.with_state_changes(shell::verbosity() > 4);
215-
let mut executor = TracingExecutor::<EthEvmNetwork>::new(
231+
let mut executor = TracingExecutor::<FEN>::new(
216232
(evm_env.clone(), tx_env),
217233
fork,
218234
evm_version,
@@ -231,10 +247,10 @@ impl RunArgs {
231247
}
232248

233249
if let Some(block) = block {
234-
let pb = init_progress(block.transactions.len() as u64, "tx");
250+
let pb = init_progress(block.transactions().len() as u64, "tx");
235251
pb.set_position(0);
236252

237-
let BlockTransactions::Full(ref txs) = block.transactions else {
253+
let BlockTransactions::Full(ref txs) = *block.transactions() else {
238254
return Err(eyre::eyre!("Could not get block txs"));
239255
};
240256

@@ -253,9 +269,7 @@ impl RunArgs {
253269
break;
254270
}
255271

256-
let tx_env = tx.as_envelope().map_or(Default::default(), |tx_envelope| {
257-
TxEnv::from_recovered_tx(tx_envelope, tx.from())
258-
});
272+
let tx_env = TxEnvFor::<FEN>::from_recovered_tx(tx.as_ref(), tx.from());
259273

260274
evm_env.cfg_env.disable_balance_check = true;
261275

@@ -266,7 +280,7 @@ impl RunArgs {
266280
format!(
267281
"Failed to execute transaction: {:?} in block {}",
268282
tx.tx_hash(),
269-
evm_env.block_env.number
283+
evm_env.block_env.number()
270284
)
271285
},
272286
)?;
@@ -283,7 +297,7 @@ impl RunArgs {
283297
format!(
284298
"Failed to deploy transaction: {:?} in block {}",
285299
tx.tx_hash(),
286-
evm_env.block_env.number
300+
evm_env.block_env.number()
287301
)
288302
});
289303
}
@@ -300,17 +314,15 @@ impl RunArgs {
300314
let result = {
301315
executor.set_trace_printer(self.trace_printer);
302316

303-
let tx_env = tx.as_envelope().map_or(Default::default(), |tx_envelope| {
304-
TxEnv::from_recovered_tx(tx_envelope, tx.from())
305-
});
317+
let tx_env = TxEnvFor::<FEN>::from_recovered_tx(tx.as_ref(), tx.from());
306318

307-
if is_impersonated_tx(tx.as_ref()) {
319+
if tx.as_ref().recover_signer().is_ok_and(|signer| signer != tx.from()) {
308320
evm_env.cfg_env.disable_balance_check = true;
309321
}
310322

311323
if let Some(to) = Transaction::to(&tx) {
312324
trace!(tx=?tx.tx_hash(), to=?to, "executing call transaction");
313-
TraceResult::try_from(executor.transact_with_env(evm_env, tx_env))?
325+
TraceResult::from(executor.transact_with_env(evm_env, tx_env)?)
314326
} else {
315327
trace!(tx=?tx.tx_hash(), "executing create transaction");
316328
TraceResult::try_from(executor.deploy_with_env(evm_env, tx_env, None))?
@@ -336,8 +348,8 @@ impl RunArgs {
336348
}
337349
}
338350

339-
pub fn fetch_contracts_bytecode_from_trace(
340-
executor: &Executor<EthEvmNetwork>,
351+
pub fn fetch_contracts_bytecode_from_trace<FEN: FoundryEvmNetwork>(
352+
executor: &Executor<FEN>,
341353
result: &TraceResult,
342354
) -> Result<HashMap<Address, Bytes>> {
343355
let mut contracts_bytecode = HashMap::default();

crates/cli/src/utils/cmd.rs

Lines changed: 12 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ use foundry_compilers::{
66
};
77
use foundry_config::{Chain, Config, NamedChain, error::ExtractConfigError, figment::Figment};
88
use foundry_evm::{
9+
core::evm::FoundryEvmNetwork,
910
executors::{DeployResult, EvmError, RawCallResult},
1011
opts::EvmOpts,
1112
traces::{
@@ -244,22 +245,25 @@ pub struct TraceResult {
244245

245246
impl TraceResult {
246247
/// Create a new [`TraceResult`] from a [`RawCallResult`].
247-
pub fn from_raw(raw: RawCallResult, trace_kind: TraceKind) -> Self {
248+
pub fn from_raw<FEN: FoundryEvmNetwork>(
249+
raw: RawCallResult<FEN>,
250+
trace_kind: TraceKind,
251+
) -> Self {
248252
let RawCallResult { gas_used, traces, reverted, .. } = raw;
249253
Self { success: !reverted, traces: traces.map(|arena| vec![(trace_kind, arena)]), gas_used }
250254
}
251255
}
252256

253-
impl From<DeployResult> for TraceResult {
254-
fn from(result: DeployResult) -> Self {
257+
impl<FEN: FoundryEvmNetwork> From<DeployResult<FEN>> for TraceResult {
258+
fn from(result: DeployResult<FEN>) -> Self {
255259
Self::from_raw(result.raw, TraceKind::Deployment)
256260
}
257261
}
258262

259-
impl TryFrom<Result<DeployResult, EvmError>> for TraceResult {
260-
type Error = EvmError;
263+
impl<FEN: FoundryEvmNetwork> TryFrom<Result<DeployResult<FEN>, EvmError<FEN>>> for TraceResult {
264+
type Error = EvmError<FEN>;
261265

262-
fn try_from(value: Result<DeployResult, EvmError>) -> Result<Self, Self::Error> {
266+
fn try_from(value: Result<DeployResult<FEN>, EvmError<FEN>>) -> Result<Self, Self::Error> {
263267
match value {
264268
Ok(result) => Ok(Self::from(result)),
265269
Err(EvmError::Execution(err)) => Ok(Self::from_raw(err.raw, TraceKind::Deployment)),
@@ -268,23 +272,12 @@ impl TryFrom<Result<DeployResult, EvmError>> for TraceResult {
268272
}
269273
}
270274

271-
impl From<RawCallResult> for TraceResult {
272-
fn from(result: RawCallResult) -> Self {
275+
impl<FEN: FoundryEvmNetwork> From<RawCallResult<FEN>> for TraceResult {
276+
fn from(result: RawCallResult<FEN>) -> Self {
273277
Self::from_raw(result, TraceKind::Execution)
274278
}
275279
}
276280

277-
impl TryFrom<Result<RawCallResult>> for TraceResult {
278-
type Error = EvmError;
279-
280-
fn try_from(value: Result<RawCallResult>) -> Result<Self, Self::Error> {
281-
match value {
282-
Ok(result) => Ok(Self::from(result)),
283-
Err(err) => Err(EvmError::from(err)),
284-
}
285-
}
286-
}
287-
288281
pub async fn print_traces(
289282
result: &mut TraceResult,
290283
decoder: &CallTraceDecoder,

0 commit comments

Comments
 (0)