foundry_evm_core/fork/
init.rsuse crate::utils::apply_chain_and_block_specific_env_changes;
use alloy_primitives::{Address, U256};
use alloy_provider::{
network::{BlockResponse, HeaderResponse},
Network, Provider,
};
use alloy_rpc_types::BlockNumberOrTag;
use alloy_transport::Transport;
use eyre::WrapErr;
use foundry_common::NON_ARCHIVE_NODE_WARNING;
use revm::primitives::{BlockEnv, CfgEnv, Env, TxEnv};
pub async fn environment<N: Network, T: Transport + Clone, P: Provider<T, N>>(
provider: &P,
memory_limit: u64,
gas_price: Option<u128>,
override_chain_id: Option<u64>,
pin_block: Option<u64>,
origin: Address,
disable_block_gas_limit: bool,
) -> eyre::Result<(Env, N::BlockResponse)> {
let block_number = if let Some(pin_block) = pin_block {
pin_block
} else {
provider.get_block_number().await.wrap_err("Failed to get latest block number")?
};
let (fork_gas_price, rpc_chain_id, block) = tokio::try_join!(
provider.get_gas_price(),
provider.get_chain_id(),
provider.get_block_by_number(BlockNumberOrTag::Number(block_number), false)
)?;
let block = if let Some(block) = block {
block
} else {
if let Ok(latest_block) = provider.get_block_number().await {
if block_number <= latest_block {
error!("{NON_ARCHIVE_NODE_WARNING}");
}
eyre::bail!(
"Failed to get block for block number: {}\nlatest block number: {}",
block_number,
latest_block
);
}
eyre::bail!("Failed to get block for block number: {}", block_number)
};
let mut cfg = CfgEnv::default();
cfg.chain_id = override_chain_id.unwrap_or(rpc_chain_id);
cfg.memory_limit = memory_limit;
cfg.limit_contract_code_size = Some(usize::MAX);
cfg.disable_eip3607 = true;
cfg.disable_block_gas_limit = disable_block_gas_limit;
let mut env = Env {
cfg,
block: BlockEnv {
number: U256::from(block.header().number()),
timestamp: U256::from(block.header().timestamp()),
coinbase: block.header().coinbase(),
difficulty: block.header().difficulty(),
prevrandao: block.header().mix_hash(),
basefee: U256::from(block.header().base_fee_per_gas().unwrap_or_default()),
gas_limit: U256::from(block.header().gas_limit()),
..Default::default()
},
tx: TxEnv {
caller: origin,
gas_price: U256::from(gas_price.unwrap_or(fork_gas_price)),
chain_id: Some(override_chain_id.unwrap_or(rpc_chain_id)),
gas_limit: block.header().gas_limit() as u64,
..Default::default()
},
};
apply_chain_and_block_specific_env_changes::<N>(&mut env, &block);
Ok((env, block))
}