anvil/eth/backend/executor/
optimism.rs1use super::AnvilBlockExecutor;
4use alloy_consensus::{Eip658Value, Receipt, ReceiptWithBloom};
5use alloy_primitives::Log;
6use foundry_evm::hardfork::FoundryHardfork;
7use foundry_primitives::FoundryReceiptEnvelope;
8use op_alloy_consensus::{OpDepositReceipt, OpDepositReceiptWithBloom};
9use revm::context_interface::result::ExecutionResult;
10
11#[cfg(feature = "base")]
12use foundry_evm::hardforks::BaseUpgrade;
13
14#[cfg(feature = "optimism")]
15use alloy_consensus::Transaction;
16#[cfg(feature = "optimism")]
17use alloy_eips::Encodable2718;
18#[cfg(feature = "optimism")]
19use foundry_evm::hardfork::OpHardfork;
20#[cfg(feature = "optimism")]
21use foundry_primitives::FoundryTxEnvelope;
22#[cfg(feature = "optimism")]
23use op_revm::{L1BlockInfo, estimate_tx_compressed_size};
24#[cfg(feature = "optimism")]
25use revm::Database;
26
27impl<E> AnvilBlockExecutor<E> {
28 #[cfg(feature = "optimism")]
30 pub(crate) fn set_optimism_hardfork(&mut self, hardfork: FoundryHardfork) {
31 self.optimism_jovian = OpHardfork::from(hardfork) >= OpHardfork::Jovian;
32 self.deposit_hardfork = Some(hardfork);
33 }
34
35 #[cfg(feature = "base")]
37 pub(crate) const fn set_base_upgrade(&mut self, upgrade: BaseUpgrade) {
38 self.deposit_hardfork = Some(FoundryHardfork::Base(upgrade));
39 }
40}
41
42#[cfg(feature = "optimism")]
44pub(crate) fn blob_gas_used<DB: Database>(
45 db: &mut DB,
46 tx: &FoundryTxEnvelope,
47 jovian: bool,
48) -> Result<u64, alloy_evm::block::BlockExecutionError> {
49 if !jovian || tx.is_deposit() {
50 return Ok(tx.blob_gas_used().unwrap_or_default());
51 }
52
53 let encoded = estimate_tx_compressed_size(tx.encoded_2718().as_ref()).saturating_div(1_000_000);
54 let scalar = L1BlockInfo::fetch_da_footprint_gas_scalar(db)
55 .map_err(alloy_evm::block::BlockExecutionError::other)?;
56 Ok(encoded.saturating_mul(u64::from(scalar)))
57}
58
59pub(crate) fn build_mined_deposit_receipt<H>(
64 result: ExecutionResult<H>,
65 hardfork: Option<FoundryHardfork>,
66 depositor_nonce: u64,
67 cumulative_gas_used: u64,
68) -> FoundryReceiptEnvelope {
69 let (deposit_nonce, deposit_receipt_version) = match hardfork {
70 Some(hardfork) => deposit_metadata(hardfork, depositor_nonce),
71 None => (Some(depositor_nonce), Some(1)),
72 };
73 build_deposit_receipt(result, cumulative_gas_used, deposit_nonce, deposit_receipt_version)
74}
75
76pub(crate) fn build_simulated_deposit_receipt<H>(
78 hardfork: FoundryHardfork,
79 caller_nonce: u64,
80 result: &ExecutionResult<H>,
81 logs: Vec<Log>,
82 cumulative_gas_used: u64,
83) -> FoundryReceiptEnvelope {
84 let (deposit_nonce, deposit_receipt_version) = deposit_metadata(hardfork, caller_nonce);
85 let receipt =
86 Receipt { status: Eip658Value::Eip658(result.is_success()), cumulative_gas_used, logs }
87 .with_bloom();
88 wrap_deposit_receipt(receipt, deposit_nonce, deposit_receipt_version)
89}
90
91fn deposit_metadata(hardfork: FoundryHardfork, caller_nonce: u64) -> (Option<u64>, Option<u64>) {
95 #[cfg(feature = "base")]
96 if matches!(hardfork, FoundryHardfork::Base(_)) {
97 let upgrade = BaseUpgrade::from(hardfork);
98 return (
99 (upgrade >= BaseUpgrade::Regolith).then_some(caller_nonce),
100 (upgrade >= BaseUpgrade::Canyon).then_some(1),
101 );
102 }
103 #[cfg(feature = "optimism")]
104 {
105 let hardfork = OpHardfork::from(hardfork);
106 (
107 (hardfork >= OpHardfork::Regolith).then_some(caller_nonce),
108 (hardfork >= OpHardfork::Canyon).then_some(1),
109 )
110 }
111 #[cfg(not(feature = "optimism"))]
112 (None, None)
113}
114
115fn build_deposit_receipt<H>(
116 result: ExecutionResult<H>,
117 cumulative_gas_used: u64,
118 deposit_nonce: Option<u64>,
119 deposit_receipt_version: Option<u64>,
120) -> FoundryReceiptEnvelope {
121 let receipt = Receipt {
122 status: Eip658Value::Eip658(result.is_success()),
123 cumulative_gas_used,
124 logs: result.into_logs(),
125 }
126 .with_bloom();
127 wrap_deposit_receipt(receipt, deposit_nonce, deposit_receipt_version)
128}
129
130fn wrap_deposit_receipt(
131 receipt: ReceiptWithBloom<Receipt>,
132 deposit_nonce: Option<u64>,
133 deposit_receipt_version: Option<u64>,
134) -> FoundryReceiptEnvelope {
135 FoundryReceiptEnvelope::Deposit(OpDepositReceiptWithBloom {
136 receipt: OpDepositReceipt {
137 inner: receipt.receipt,
138 deposit_nonce,
139 deposit_receipt_version,
140 },
141 logs_bloom: receipt.logs_bloom,
142 })
143}