foundry_evm_core/fork/
init.rs
1use crate::utils::apply_chain_and_block_specific_env_changes;
2use alloy_consensus::BlockHeader;
3use alloy_primitives::{Address, U256};
4use alloy_provider::{network::BlockResponse, Network, Provider};
5use alloy_rpc_types::BlockNumberOrTag;
6use eyre::WrapErr;
7use foundry_common::NON_ARCHIVE_NODE_WARNING;
8use revm::primitives::{BlockEnv, CfgEnv, Env, TxEnv};
9
10pub async fn environment<N: Network, P: Provider<N>>(
13 provider: &P,
14 memory_limit: u64,
15 gas_price: Option<u128>,
16 override_chain_id: Option<u64>,
17 pin_block: Option<u64>,
18 origin: Address,
19 disable_block_gas_limit: bool,
20) -> eyre::Result<(Env, N::BlockResponse)> {
21 let block_number = if let Some(pin_block) = pin_block {
22 pin_block
23 } else {
24 provider.get_block_number().await.wrap_err("failed to get latest block number")?
25 };
26 let (fork_gas_price, rpc_chain_id, block) = tokio::try_join!(
27 provider.get_gas_price(),
28 provider.get_chain_id(),
29 provider.get_block_by_number(BlockNumberOrTag::Number(block_number))
30 )?;
31 let block = if let Some(block) = block {
32 block
33 } else {
34 if let Ok(latest_block) = provider.get_block_number().await {
35 if block_number <= latest_block {
39 error!("{NON_ARCHIVE_NODE_WARNING}");
40 }
41 eyre::bail!(
42 "failed to get block for block number: {block_number}; \
43 latest block number: {latest_block}"
44 );
45 }
46 eyre::bail!("failed to get block for block number: {block_number}")
47 };
48
49 let mut cfg = CfgEnv::default();
50 cfg.chain_id = override_chain_id.unwrap_or(rpc_chain_id);
51 cfg.memory_limit = memory_limit;
52 cfg.limit_contract_code_size = Some(usize::MAX);
53 cfg.disable_eip3607 = true;
57 cfg.disable_block_gas_limit = disable_block_gas_limit;
58
59 let mut env = Env {
60 cfg,
61 block: BlockEnv {
62 number: U256::from(block.header().number()),
63 timestamp: U256::from(block.header().timestamp()),
64 coinbase: block.header().beneficiary(),
65 difficulty: block.header().difficulty(),
66 prevrandao: block.header().mix_hash(),
67 basefee: U256::from(block.header().base_fee_per_gas().unwrap_or_default()),
68 gas_limit: U256::from(block.header().gas_limit()),
69 ..Default::default()
70 },
71 tx: TxEnv {
72 caller: origin,
73 gas_price: U256::from(gas_price.unwrap_or(fork_gas_price)),
74 chain_id: Some(override_chain_id.unwrap_or(rpc_chain_id)),
75 gas_limit: block.header().gas_limit() as u64,
76 ..Default::default()
77 },
78 };
79
80 apply_chain_and_block_specific_env_changes::<N>(&mut env, &block);
81
82 Ok((env, block))
83}