reth_optimism_rpc/eth/
receipt.rs

1//! Loads and formats OP receipt RPC response.
2
3use alloy_consensus::transaction::TransactionMeta;
4use alloy_eips::eip2718::Encodable2718;
5use alloy_rpc_types_eth::{Log, TransactionReceipt};
6use op_alloy_consensus::{OpDepositReceipt, OpDepositReceiptWithBloom, OpReceiptEnvelope};
7use op_alloy_rpc_types::{L1BlockInfo, OpTransactionReceipt, OpTransactionReceiptFields};
8use reth_node_api::{FullNodeComponents, NodeTypes};
9use reth_optimism_chainspec::OpChainSpec;
10use reth_optimism_evm::RethL1BlockInfo;
11use reth_optimism_forks::OpHardforks;
12use reth_optimism_primitives::{OpReceipt, OpTransactionSigned};
13use reth_provider::{ChainSpecProvider, ReceiptProvider, TransactionsProvider};
14use reth_rpc_eth_api::{helpers::LoadReceipt, FromEthApiError, RpcReceipt};
15use reth_rpc_eth_types::{receipt::build_receipt, EthApiError};
16
17use crate::{OpEthApi, OpEthApiError};
18
19impl<N> LoadReceipt for OpEthApi<N>
20where
21    Self: Send + Sync,
22    N: FullNodeComponents<Types: NodeTypes<ChainSpec = OpChainSpec>>,
23    Self::Provider: TransactionsProvider<Transaction = OpTransactionSigned>
24        + ReceiptProvider<Receipt = OpReceipt>,
25{
26    async fn build_transaction_receipt(
27        &self,
28        tx: OpTransactionSigned,
29        meta: TransactionMeta,
30        receipt: OpReceipt,
31    ) -> Result<RpcReceipt<Self::NetworkTypes>, Self::Error> {
32        let (block, receipts) = self
33            .inner
34            .eth_api
35            .cache()
36            .get_block_and_receipts(meta.block_hash)
37            .await
38            .map_err(Self::Error::from_eth_err)?
39            .ok_or(Self::Error::from_eth_err(EthApiError::HeaderNotFound(
40                meta.block_hash.into(),
41            )))?;
42
43        let mut l1_block_info =
44            reth_optimism_evm::extract_l1_info(block.body()).map_err(OpEthApiError::from)?;
45
46        Ok(OpReceiptBuilder::new(
47            &self.inner.eth_api.provider().chain_spec(),
48            &tx,
49            meta,
50            &receipt,
51            &receipts,
52            &mut l1_block_info,
53        )?
54        .build())
55    }
56}
57
58/// L1 fee and data gas for a non-deposit transaction, or deposit nonce and receipt version for a
59/// deposit transaction.
60#[derive(Debug, Clone)]
61pub struct OpReceiptFieldsBuilder {
62    /// Block number.
63    pub block_number: u64,
64    /// Block timestamp.
65    pub block_timestamp: u64,
66    /// The L1 fee for transaction.
67    pub l1_fee: Option<u128>,
68    /// L1 gas used by transaction.
69    pub l1_data_gas: Option<u128>,
70    /// L1 fee scalar.
71    pub l1_fee_scalar: Option<f64>,
72    /* ---------------------------------------- Bedrock ---------------------------------------- */
73    /// The base fee of the L1 origin block.
74    pub l1_base_fee: Option<u128>,
75    /* --------------------------------------- Regolith ---------------------------------------- */
76    /// Deposit nonce, if this is a deposit transaction.
77    pub deposit_nonce: Option<u64>,
78    /* ---------------------------------------- Canyon ----------------------------------------- */
79    /// Deposit receipt version, if this is a deposit transaction.
80    pub deposit_receipt_version: Option<u64>,
81    /* ---------------------------------------- Ecotone ---------------------------------------- */
82    /// The current L1 fee scalar.
83    pub l1_base_fee_scalar: Option<u128>,
84    /// The current L1 blob base fee.
85    pub l1_blob_base_fee: Option<u128>,
86    /// The current L1 blob base fee scalar.
87    pub l1_blob_base_fee_scalar: Option<u128>,
88    /// The current operator fee scalar.
89    pub operator_fee_scalar: Option<u128>,
90    /// The current L1 blob base fee scalar.
91    pub operator_fee_constant: Option<u128>,
92}
93
94impl OpReceiptFieldsBuilder {
95    /// Returns a new builder.
96    pub const fn new(block_timestamp: u64, block_number: u64) -> Self {
97        Self {
98            block_number,
99            block_timestamp,
100            l1_fee: None,
101            l1_data_gas: None,
102            l1_fee_scalar: None,
103            l1_base_fee: None,
104            deposit_nonce: None,
105            deposit_receipt_version: None,
106            l1_base_fee_scalar: None,
107            l1_blob_base_fee: None,
108            l1_blob_base_fee_scalar: None,
109            operator_fee_scalar: None,
110            operator_fee_constant: None,
111        }
112    }
113
114    /// Applies [`L1BlockInfo`](op_revm::L1BlockInfo).
115    pub fn l1_block_info(
116        mut self,
117        chain_spec: &OpChainSpec,
118        tx: &OpTransactionSigned,
119        l1_block_info: &mut op_revm::L1BlockInfo,
120    ) -> Result<Self, OpEthApiError> {
121        let raw_tx = tx.encoded_2718();
122        let block_number = self.block_number;
123        let timestamp = self.block_timestamp;
124
125        self.l1_fee = Some(
126            l1_block_info
127                .l1_tx_data_fee(chain_spec, timestamp, block_number, &raw_tx, tx.is_deposit())
128                .map_err(|_| OpEthApiError::L1BlockFeeError)?
129                .saturating_to(),
130        );
131
132        self.l1_data_gas = Some(
133            l1_block_info
134                .l1_data_gas(chain_spec, timestamp, block_number, &raw_tx)
135                .map_err(|_| OpEthApiError::L1BlockGasError)?
136                .saturating_add(l1_block_info.l1_fee_overhead.unwrap_or_default())
137                .saturating_to(),
138        );
139
140        self.l1_fee_scalar = (!chain_spec.is_ecotone_active_at_timestamp(timestamp))
141            .then_some(f64::from(l1_block_info.l1_base_fee_scalar) / 1_000_000.0);
142
143        self.l1_base_fee = Some(l1_block_info.l1_base_fee.saturating_to());
144        self.l1_base_fee_scalar = Some(l1_block_info.l1_base_fee_scalar.saturating_to());
145        self.l1_blob_base_fee = l1_block_info.l1_blob_base_fee.map(|fee| fee.saturating_to());
146        self.l1_blob_base_fee_scalar =
147            l1_block_info.l1_blob_base_fee_scalar.map(|scalar| scalar.saturating_to());
148
149        // If the operator fee params are both set to 0, we don't add them to the receipt.
150        let operator_fee_scalar_has_non_zero_value: bool =
151            l1_block_info.operator_fee_scalar.is_some_and(|scalar| !scalar.is_zero());
152
153        let operator_fee_constant_has_non_zero_value =
154            l1_block_info.operator_fee_constant.is_some_and(|constant| !constant.is_zero());
155
156        if operator_fee_scalar_has_non_zero_value || operator_fee_constant_has_non_zero_value {
157            self.operator_fee_scalar =
158                l1_block_info.operator_fee_scalar.map(|scalar| scalar.saturating_to());
159            self.operator_fee_constant =
160                l1_block_info.operator_fee_constant.map(|constant| constant.saturating_to());
161        }
162
163        Ok(self)
164    }
165
166    /// Applies deposit transaction metadata: deposit nonce.
167    pub const fn deposit_nonce(mut self, nonce: Option<u64>) -> Self {
168        self.deposit_nonce = nonce;
169        self
170    }
171
172    /// Applies deposit transaction metadata: deposit receipt version.
173    pub const fn deposit_version(mut self, version: Option<u64>) -> Self {
174        self.deposit_receipt_version = version;
175        self
176    }
177
178    /// Builds the [`OpTransactionReceiptFields`] object.
179    pub const fn build(self) -> OpTransactionReceiptFields {
180        let Self {
181            block_number: _,    // used to compute other fields
182            block_timestamp: _, // used to compute other fields
183            l1_fee,
184            l1_data_gas: l1_gas_used,
185            l1_fee_scalar,
186            l1_base_fee: l1_gas_price,
187            deposit_nonce,
188            deposit_receipt_version,
189            l1_base_fee_scalar,
190            l1_blob_base_fee,
191            l1_blob_base_fee_scalar,
192            operator_fee_scalar,
193            operator_fee_constant,
194        } = self;
195
196        OpTransactionReceiptFields {
197            l1_block_info: L1BlockInfo {
198                l1_gas_price,
199                l1_gas_used,
200                l1_fee,
201                l1_fee_scalar,
202                l1_base_fee_scalar,
203                l1_blob_base_fee,
204                l1_blob_base_fee_scalar,
205                operator_fee_scalar,
206                operator_fee_constant,
207            },
208            deposit_nonce,
209            deposit_receipt_version,
210        }
211    }
212}
213
214/// Builds an [`OpTransactionReceipt`].
215#[derive(Debug)]
216pub struct OpReceiptBuilder {
217    /// Core receipt, has all the fields of an L1 receipt and is the basis for the OP receipt.
218    pub core_receipt: TransactionReceipt<OpReceiptEnvelope<Log>>,
219    /// Additional OP receipt fields.
220    pub op_receipt_fields: OpTransactionReceiptFields,
221}
222
223impl OpReceiptBuilder {
224    /// Returns a new builder.
225    pub fn new(
226        chain_spec: &OpChainSpec,
227        transaction: &OpTransactionSigned,
228        meta: TransactionMeta,
229        receipt: &OpReceipt,
230        all_receipts: &[OpReceipt],
231        l1_block_info: &mut op_revm::L1BlockInfo,
232    ) -> Result<Self, OpEthApiError> {
233        let timestamp = meta.timestamp;
234        let block_number = meta.block_number;
235        let core_receipt =
236            build_receipt(transaction, meta, receipt, all_receipts, None, |receipt_with_bloom| {
237                match receipt {
238                    OpReceipt::Legacy(_) => OpReceiptEnvelope::<Log>::Legacy(receipt_with_bloom),
239                    OpReceipt::Eip2930(_) => OpReceiptEnvelope::<Log>::Eip2930(receipt_with_bloom),
240                    OpReceipt::Eip1559(_) => OpReceiptEnvelope::<Log>::Eip1559(receipt_with_bloom),
241                    OpReceipt::Eip7702(_) => OpReceiptEnvelope::<Log>::Eip7702(receipt_with_bloom),
242                    OpReceipt::Deposit(receipt) => {
243                        OpReceiptEnvelope::<Log>::Deposit(OpDepositReceiptWithBloom::<Log> {
244                            receipt: OpDepositReceipt::<Log> {
245                                inner: receipt_with_bloom.receipt,
246                                deposit_nonce: receipt.deposit_nonce,
247                                deposit_receipt_version: receipt.deposit_receipt_version,
248                            },
249                            logs_bloom: receipt_with_bloom.logs_bloom,
250                        })
251                    }
252                }
253            })?;
254
255        let op_receipt_fields = OpReceiptFieldsBuilder::new(timestamp, block_number)
256            .l1_block_info(chain_spec, transaction, l1_block_info)?
257            .build();
258
259        Ok(Self { core_receipt, op_receipt_fields })
260    }
261
262    /// Builds [`OpTransactionReceipt`] by combing core (l1) receipt fields and additional OP
263    /// receipt fields.
264    pub fn build(self) -> OpTransactionReceipt {
265        let Self { core_receipt: inner, op_receipt_fields } = self;
266
267        let OpTransactionReceiptFields { l1_block_info, .. } = op_receipt_fields;
268
269        OpTransactionReceipt { inner, l1_block_info }
270    }
271}
272
273#[cfg(test)]
274mod test {
275    use super::*;
276    use alloy_consensus::{Block, BlockBody};
277    use alloy_primitives::{hex, U256};
278    use op_alloy_network::eip2718::Decodable2718;
279    use reth_optimism_chainspec::{BASE_MAINNET, OP_MAINNET};
280
281    /// OP Mainnet transaction at index 0 in block 124665056.
282    ///
283    /// <https://optimistic.etherscan.io/tx/0x312e290cf36df704a2217b015d6455396830b0ce678b860ebfcc30f41403d7b1>
284    const TX_SET_L1_BLOCK_OP_MAINNET_BLOCK_124665056: [u8; 251] = hex!("7ef8f8a0683079df94aa5b9cf86687d739a60a9b4f0835e520ec4d664e2e415dca17a6df94deaddeaddeaddeaddeaddeaddeaddeaddead00019442000000000000000000000000000000000000158080830f424080b8a4440a5e200000146b000f79c500000000000000040000000066d052e700000000013ad8a3000000000000000000000000000000000000000000000000000000003ef1278700000000000000000000000000000000000000000000000000000000000000012fdf87b89884a61e74b322bbcf60386f543bfae7827725efaaf0ab1de2294a590000000000000000000000006887246668a3b87f54deb3b94ba47a6f63f32985");
285
286    /// OP Mainnet transaction at index 1 in block 124665056.
287    ///
288    /// <https://optimistic.etherscan.io/tx/0x1059e8004daff32caa1f1b1ef97fe3a07a8cf40508f5b835b66d9420d87c4a4a>
289    const TX_1_OP_MAINNET_BLOCK_124665056: [u8; 1176] = hex!("02f904940a8303fba78401d6d2798401db2b6d830493e0943e6f4f7866654c18f536170780344aa8772950b680b904246a761202000000000000000000000000087000a300de7200382b55d40045000000e5d60e0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000014000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003a0000000000000000000000000000000000000000000000000000000000000022482ad56cb0000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000120000000000000000000000000dc6ff44d5d932cbd77b52e5612ba0529dc6226f1000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000044095ea7b300000000000000000000000021c4928109acb0659a88ae5329b5374a3024694c0000000000000000000000000000000000000000000000049b9ca9a6943400000000000000000000000000000000000000000000000000000000000000000000000000000000000021c4928109acb0659a88ae5329b5374a3024694c000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000024b6b55f250000000000000000000000000000000000000000000000049b9ca9a694340000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000415ec214a3950bea839a7e6fbb0ba1540ac2076acd50820e2d5ef83d0902cdffb24a47aff7de5190290769c4f0a9c6fabf63012986a0d590b1b571547a8c7050ea1b00000000000000000000000000000000000000000000000000000000000000c080a06db770e6e25a617fe9652f0958bd9bd6e49281a53036906386ed39ec48eadf63a07f47cf51a4a40b4494cf26efc686709a9b03939e20ee27e59682f5faa536667e");
290
291    /// Timestamp of OP mainnet block 124665056.
292    ///
293    /// <https://optimistic.etherscan.io/block/124665056>
294    const BLOCK_124665056_TIMESTAMP: u64 = 1724928889;
295
296    /// L1 block info for transaction at index 1 in block 124665056.
297    ///
298    /// <https://optimistic.etherscan.io/tx/0x1059e8004daff32caa1f1b1ef97fe3a07a8cf40508f5b835b66d9420d87c4a4a>
299    const TX_META_TX_1_OP_MAINNET_BLOCK_124665056: OpTransactionReceiptFields =
300        OpTransactionReceiptFields {
301            l1_block_info: L1BlockInfo {
302                l1_gas_price: Some(1055991687), // since bedrock l1 base fee
303                l1_gas_used: Some(4471),
304                l1_fee: Some(24681034813),
305                l1_fee_scalar: None,
306                l1_base_fee_scalar: Some(5227),
307                l1_blob_base_fee: Some(1),
308                l1_blob_base_fee_scalar: Some(1014213),
309                operator_fee_scalar: None,
310                operator_fee_constant: None,
311            },
312            deposit_nonce: None,
313            deposit_receipt_version: None,
314        };
315
316    #[test]
317    fn op_receipt_fields_from_block_and_tx() {
318        // rig
319        let tx_0 = OpTransactionSigned::decode_2718(
320            &mut TX_SET_L1_BLOCK_OP_MAINNET_BLOCK_124665056.as_slice(),
321        )
322        .unwrap();
323
324        let tx_1 =
325            OpTransactionSigned::decode_2718(&mut TX_1_OP_MAINNET_BLOCK_124665056.as_slice())
326                .unwrap();
327
328        let block: Block<OpTransactionSigned> = Block {
329            body: BlockBody { transactions: [tx_0, tx_1.clone()].to_vec(), ..Default::default() },
330            ..Default::default()
331        };
332
333        let mut l1_block_info =
334            reth_optimism_evm::extract_l1_info(&block.body).expect("should extract l1 info");
335
336        // test
337        assert!(OP_MAINNET.is_fjord_active_at_timestamp(BLOCK_124665056_TIMESTAMP));
338
339        let receipt_meta = OpReceiptFieldsBuilder::new(BLOCK_124665056_TIMESTAMP, 124665056)
340            .l1_block_info(&OP_MAINNET, &tx_1, &mut l1_block_info)
341            .expect("should parse revm l1 info")
342            .build();
343
344        let L1BlockInfo {
345            l1_gas_price,
346            l1_gas_used,
347            l1_fee,
348            l1_fee_scalar,
349            l1_base_fee_scalar,
350            l1_blob_base_fee,
351            l1_blob_base_fee_scalar,
352            operator_fee_scalar,
353            operator_fee_constant,
354        } = receipt_meta.l1_block_info;
355
356        assert_eq!(
357            l1_gas_price, TX_META_TX_1_OP_MAINNET_BLOCK_124665056.l1_block_info.l1_gas_price,
358            "incorrect l1 base fee (former gas price)"
359        );
360        assert_eq!(
361            l1_gas_used, TX_META_TX_1_OP_MAINNET_BLOCK_124665056.l1_block_info.l1_gas_used,
362            "incorrect l1 gas used"
363        );
364        assert_eq!(
365            l1_fee, TX_META_TX_1_OP_MAINNET_BLOCK_124665056.l1_block_info.l1_fee,
366            "incorrect l1 fee"
367        );
368        assert_eq!(
369            l1_fee_scalar, TX_META_TX_1_OP_MAINNET_BLOCK_124665056.l1_block_info.l1_fee_scalar,
370            "incorrect l1 fee scalar"
371        );
372        assert_eq!(
373            l1_base_fee_scalar,
374            TX_META_TX_1_OP_MAINNET_BLOCK_124665056.l1_block_info.l1_base_fee_scalar,
375            "incorrect l1 base fee scalar"
376        );
377        assert_eq!(
378            l1_blob_base_fee,
379            TX_META_TX_1_OP_MAINNET_BLOCK_124665056.l1_block_info.l1_blob_base_fee,
380            "incorrect l1 blob base fee"
381        );
382        assert_eq!(
383            l1_blob_base_fee_scalar,
384            TX_META_TX_1_OP_MAINNET_BLOCK_124665056.l1_block_info.l1_blob_base_fee_scalar,
385            "incorrect l1 blob base fee scalar"
386        );
387        assert_eq!(
388            operator_fee_scalar,
389            TX_META_TX_1_OP_MAINNET_BLOCK_124665056.l1_block_info.operator_fee_scalar,
390            "incorrect operator fee scalar"
391        );
392        assert_eq!(
393            operator_fee_constant,
394            TX_META_TX_1_OP_MAINNET_BLOCK_124665056.l1_block_info.operator_fee_constant,
395            "incorrect operator fee constant"
396        );
397    }
398
399    #[test]
400    fn op_non_zero_operator_fee_params_included_in_receipt() {
401        let tx_1 =
402            OpTransactionSigned::decode_2718(&mut TX_1_OP_MAINNET_BLOCK_124665056.as_slice())
403                .unwrap();
404
405        let mut l1_block_info = op_revm::L1BlockInfo::default();
406
407        l1_block_info.operator_fee_scalar = Some(U256::ZERO);
408        l1_block_info.operator_fee_constant = Some(U256::from(2));
409
410        let receipt_meta = OpReceiptFieldsBuilder::new(BLOCK_124665056_TIMESTAMP, 124665056)
411            .l1_block_info(&OP_MAINNET, &tx_1, &mut l1_block_info)
412            .expect("should parse revm l1 info")
413            .build();
414
415        let L1BlockInfo { operator_fee_scalar, operator_fee_constant, .. } =
416            receipt_meta.l1_block_info;
417
418        assert_eq!(operator_fee_scalar, Some(0), "incorrect operator fee scalar");
419        assert_eq!(operator_fee_constant, Some(2), "incorrect operator fee constant");
420    }
421
422    #[test]
423    fn op_zero_operator_fee_params_not_included_in_receipt() {
424        let tx_1 =
425            OpTransactionSigned::decode_2718(&mut TX_1_OP_MAINNET_BLOCK_124665056.as_slice())
426                .unwrap();
427
428        let mut l1_block_info = op_revm::L1BlockInfo::default();
429
430        l1_block_info.operator_fee_scalar = Some(U256::ZERO);
431        l1_block_info.operator_fee_constant = Some(U256::ZERO);
432
433        let receipt_meta = OpReceiptFieldsBuilder::new(BLOCK_124665056_TIMESTAMP, 124665056)
434            .l1_block_info(&OP_MAINNET, &tx_1, &mut l1_block_info)
435            .expect("should parse revm l1 info")
436            .build();
437
438        let L1BlockInfo { operator_fee_scalar, operator_fee_constant, .. } =
439            receipt_meta.l1_block_info;
440
441        assert_eq!(operator_fee_scalar, None, "incorrect operator fee scalar");
442        assert_eq!(operator_fee_constant, None, "incorrect operator fee constant");
443    }
444
445    // <https://github.com/paradigmxyz/reth/issues/12177>
446    #[test]
447    fn base_receipt_gas_fields() {
448        // https://basescan.org/tx/0x510fd4c47d78ba9f97c91b0f2ace954d5384c169c9545a77a373cf3ef8254e6e
449        let system = hex!("7ef8f8a0389e292420bcbf9330741f72074e39562a09ff5a00fd22e4e9eee7e34b81bca494deaddeaddeaddeaddeaddeaddeaddeaddead00019442000000000000000000000000000000000000158080830f424080b8a4440a5e20000008dd00101c120000000000000004000000006721035b00000000014189960000000000000000000000000000000000000000000000000000000349b4dcdc000000000000000000000000000000000000000000000000000000004ef9325cc5991ce750960f636ca2ffbb6e209bb3ba91412f21dd78c14ff154d1930f1f9a0000000000000000000000005050f69a9786f081509234f1a7f4684b5e5b76c9");
450        let tx_0 = OpTransactionSigned::decode_2718(&mut &system[..]).unwrap();
451
452        let block: alloy_consensus::Block<OpTransactionSigned> = Block {
453            body: BlockBody { transactions: vec![tx_0], ..Default::default() },
454            ..Default::default()
455        };
456        let mut l1_block_info =
457            reth_optimism_evm::extract_l1_info(&block.body).expect("should extract l1 info");
458
459        // https://basescan.org/tx/0xf9420cbaf66a2dda75a015488d37262cbfd4abd0aad7bb2be8a63e14b1fa7a94
460        let tx = hex!("02f86c8221058034839a4ae283021528942f16386bb37709016023232523ff6d9daf444be380841249c58bc080a001b927eda2af9b00b52a57be0885e0303c39dd2831732e14051c2336470fd468a0681bf120baf562915841a48601c2b54a6742511e535cf8f71c95115af7ff63bd");
461        let tx_1 = OpTransactionSigned::decode_2718(&mut &tx[..]).unwrap();
462
463        let receipt_meta = OpReceiptFieldsBuilder::new(1730216981, 21713817)
464            .l1_block_info(&BASE_MAINNET, &tx_1, &mut l1_block_info)
465            .expect("should parse revm l1 info")
466            .build();
467
468        let L1BlockInfo {
469            l1_gas_price,
470            l1_gas_used,
471            l1_fee,
472            l1_fee_scalar,
473            l1_base_fee_scalar,
474            l1_blob_base_fee,
475            l1_blob_base_fee_scalar,
476            operator_fee_scalar,
477            operator_fee_constant,
478        } = receipt_meta.l1_block_info;
479
480        assert_eq!(l1_gas_price, Some(14121491676), "incorrect l1 base fee (former gas price)");
481        assert_eq!(l1_gas_used, Some(1600), "incorrect l1 gas used");
482        assert_eq!(l1_fee, Some(191150293412), "incorrect l1 fee");
483        assert!(l1_fee_scalar.is_none(), "incorrect l1 fee scalar");
484        assert_eq!(l1_base_fee_scalar, Some(2269), "incorrect l1 base fee scalar");
485        assert_eq!(l1_blob_base_fee, Some(1324954204), "incorrect l1 blob base fee");
486        assert_eq!(l1_blob_base_fee_scalar, Some(1055762), "incorrect l1 blob base fee scalar");
487        assert_eq!(operator_fee_scalar, None, "incorrect operator fee scalar");
488        assert_eq!(operator_fee_constant, None, "incorrect operator fee constant");
489    }
490}