reth_optimism_evm/
execute.rs1pub type OpExecutorProvider = crate::OpEvmConfig;
5
6#[cfg(test)]
7mod tests {
8 use crate::{OpEvmConfig, OpRethReceiptBuilder};
9 use alloc::sync::Arc;
10 use alloy_consensus::{Block, BlockBody, Header, SignableTransaction, TxEip1559};
11 use alloy_primitives::{b256, Address, Signature, StorageKey, StorageValue, U256};
12 use op_alloy_consensus::TxDeposit;
13 use op_revm::constants::L1_BLOCK_CONTRACT;
14 use reth_chainspec::MIN_TRANSACTION_GAS;
15 use reth_evm::execute::{BasicBlockExecutor, Executor};
16 use reth_optimism_chainspec::{OpChainSpec, OpChainSpecBuilder};
17 use reth_optimism_primitives::{OpReceipt, OpTransactionSigned};
18 use reth_primitives_traits::{Account, RecoveredBlock};
19 use reth_revm::{database::StateProviderDatabase, test_utils::StateProviderTest};
20 use std::{collections::HashMap, str::FromStr};
21
22 fn create_op_state_provider() -> StateProviderTest {
23 let mut db = StateProviderTest::default();
24
25 let l1_block_contract_account =
26 Account { balance: U256::ZERO, bytecode_hash: None, nonce: 1 };
27
28 let mut l1_block_storage = HashMap::default();
29 l1_block_storage.insert(StorageKey::with_last_byte(1), StorageValue::from(1000000000));
31 l1_block_storage.insert(StorageKey::with_last_byte(5), StorageValue::from(188));
33 l1_block_storage.insert(StorageKey::with_last_byte(6), StorageValue::from(684000));
35 l1_block_storage.insert(
37 StorageKey::with_last_byte(3),
38 StorageValue::from_str(
39 "0x0000000000000000000000000000000000001db0000d27300000000000000005",
40 )
41 .unwrap(),
42 );
43
44 db.insert_account(L1_BLOCK_CONTRACT, l1_block_contract_account, None, l1_block_storage);
45
46 db
47 }
48
49 fn evm_config(chain_spec: Arc<OpChainSpec>) -> OpEvmConfig {
50 OpEvmConfig::new(chain_spec, OpRethReceiptBuilder::default())
51 }
52
53 #[test]
54 fn op_deposit_fields_pre_canyon() {
55 let header = Header {
56 timestamp: 1,
57 number: 1,
58 gas_limit: 1_000_000,
59 gas_used: 42_000,
60 receipts_root: b256!(
61 "0x83465d1e7d01578c0d609be33570f91242f013e9e295b0879905346abbd63731"
62 ),
63 ..Default::default()
64 };
65
66 let mut db = create_op_state_provider();
67
68 let addr = Address::ZERO;
69 let account = Account { balance: U256::MAX, ..Account::default() };
70 db.insert_account(addr, account, None, HashMap::default());
71
72 let chain_spec = Arc::new(OpChainSpecBuilder::base_mainnet().regolith_activated().build());
73
74 let tx: OpTransactionSigned = TxEip1559 {
75 chain_id: chain_spec.chain.id(),
76 nonce: 0,
77 gas_limit: MIN_TRANSACTION_GAS,
78 to: addr.into(),
79 ..Default::default()
80 }
81 .into_signed(Signature::test_signature())
82 .into();
83
84 let tx_deposit: OpTransactionSigned = TxDeposit {
85 from: addr,
86 to: addr.into(),
87 gas_limit: MIN_TRANSACTION_GAS,
88 ..Default::default()
89 }
90 .into();
91
92 let provider = evm_config(chain_spec);
93 let mut executor = BasicBlockExecutor::new(provider, StateProviderDatabase::new(&db));
94
95 executor.with_state_mut(|state| {
97 state.load_cache_account(L1_BLOCK_CONTRACT).unwrap();
98 });
99
100 let output = executor
102 .execute(&RecoveredBlock::new_unhashed(
103 Block {
104 header,
105 body: BlockBody { transactions: vec![tx, tx_deposit], ..Default::default() },
106 },
107 vec![addr, addr],
108 ))
109 .unwrap();
110
111 let receipts = &output.receipts;
112 let tx_receipt = &receipts[0];
113 let deposit_receipt = &receipts[1];
114
115 assert!(!matches!(tx_receipt, OpReceipt::Deposit(_)));
116 let OpReceipt::Deposit(deposit_receipt) = deposit_receipt else {
118 panic!("expected deposit")
119 };
120 assert!(deposit_receipt.deposit_nonce.is_some());
121 assert!(deposit_receipt.deposit_receipt_version.is_none());
123 }
124
125 #[test]
126 fn op_deposit_fields_post_canyon() {
127 let header = Header {
129 timestamp: 2,
130 number: 1,
131 gas_limit: 1_000_000,
132 gas_used: 42_000,
133 receipts_root: b256!(
134 "0xfffc85c4004fd03c7bfbe5491fae98a7473126c099ac11e8286fd0013f15f908"
135 ),
136 ..Default::default()
137 };
138
139 let mut db = create_op_state_provider();
140 let addr = Address::ZERO;
141 let account = Account { balance: U256::MAX, ..Account::default() };
142
143 db.insert_account(addr, account, None, HashMap::default());
144
145 let chain_spec = Arc::new(OpChainSpecBuilder::base_mainnet().canyon_activated().build());
146
147 let tx: OpTransactionSigned = TxEip1559 {
148 chain_id: chain_spec.chain.id(),
149 nonce: 0,
150 gas_limit: MIN_TRANSACTION_GAS,
151 to: addr.into(),
152 ..Default::default()
153 }
154 .into_signed(Signature::test_signature())
155 .into();
156
157 let tx_deposit: OpTransactionSigned = TxDeposit {
158 from: addr,
159 to: addr.into(),
160 gas_limit: MIN_TRANSACTION_GAS,
161 ..Default::default()
162 }
163 .into();
164
165 let provider = evm_config(chain_spec);
166 let mut executor = BasicBlockExecutor::new(provider, StateProviderDatabase::new(&db));
167
168 executor.with_state_mut(|state| {
170 state.load_cache_account(L1_BLOCK_CONTRACT).unwrap();
171 });
172
173 let output = executor
175 .execute(&RecoveredBlock::new_unhashed(
176 Block {
177 header,
178 body: BlockBody { transactions: vec![tx, tx_deposit], ..Default::default() },
179 },
180 vec![addr, addr],
181 ))
182 .expect("Executing a block while canyon is active should not fail");
183
184 let receipts = &output.receipts;
185 let tx_receipt = &receipts[0];
186 let deposit_receipt = &receipts[1];
187
188 assert!(!matches!(tx_receipt, OpReceipt::Deposit(_)));
190 let OpReceipt::Deposit(deposit_receipt) = deposit_receipt else {
191 panic!("expected deposit")
192 };
193 assert_eq!(deposit_receipt.deposit_receipt_version, Some(1));
194
195 assert!(deposit_receipt.deposit_nonce.is_some());
197 }
198}