1use std::sync::Arc;
2
3use crate::{
4 contracts::{
5 counter::{COUNTER_BYTECODE, COUNTER_TEST_ADDRESS},
6 reverts::{REVERT_BYTECODE, REVERT_TEST_ADDRESS},
7 system::{
8 HOST_ORDERS_BYTECODE, HOST_PASSAGE_BYTECODE, RU_ORDERS_BYTECODE, RU_PASSAGE_BYTECODE,
9 },
10 token::{allowances_slot_for, balance_slot_for, deploy_wbtc_at, deploy_weth_at},
11 },
12 users::TEST_USERS,
13};
14use alloy::{
15 consensus::constants::ETH_TO_WEI,
16 primitives::{Address, Bytes, KECCAK256_EMPTY, U256},
17};
18use signet_constants::test_utils::*;
19use signet_sim::{AcctInfo, BlockBuild, HostEnv, RollupEnv, StateSource};
20use trevm::{
21 helpers::Ctx,
22 revm::{
23 context::CfgEnv,
24 database::in_memory_db::InMemoryDB,
25 inspector::NoOpInspector,
26 primitives::hardfork::SpecId,
27 state::{Account, AccountInfo, Bytecode, EvmState, EvmStorageSlot},
28 Database, DatabaseCommit, Inspector,
29 },
30 Cfg, NoopBlock,
31};
32
33pub fn test_signet_evm() -> signet_evm::EvmNeedsBlock<InMemoryDB> {
45 test_signet_evm_with_inspector(NoOpInspector)
46}
47
48pub fn test_signet_evm_with_inspector<I>(inspector: I) -> signet_evm::EvmNeedsBlock<InMemoryDB, I>
60where
61 I: Inspector<Ctx<InMemoryDB>>,
62{
63 let mut db = InMemoryDB::default();
64 setup_rollup_db(&mut db).unwrap();
65
66 signet_evm::signet_evm_with_inspector(db, inspector, TEST_SYS).fill_cfg(&TestCfg)
67}
68
69#[derive(Debug, Clone, Copy, PartialEq, Eq)]
71pub struct TestCfg;
72
73impl Cfg for TestCfg {
74 fn fill_cfg_env(&self, cfg_env: &mut CfgEnv) {
75 let CfgEnv { chain_id, spec, .. } = cfg_env;
76
77 *chain_id = RU_CHAIN_ID;
78 *spec = SpecId::default();
79 }
80}
81
82#[derive(Debug, Clone, Copy, PartialEq, Eq)]
84pub struct HostTestCfg;
85
86impl Cfg for HostTestCfg {
87 fn fill_cfg_env(&self, cfg_env: &mut CfgEnv) {
88 let CfgEnv { chain_id, spec, .. } = cfg_env;
89
90 *chain_id = HOST_CHAIN_ID;
91 *spec = SpecId::default();
92 }
93}
94
95pub fn rollup_sim_env() -> RollupEnv<Arc<InMemoryDB>, NoOpInspector> {
97 let mut ru_db = InMemoryDB::default();
98
99 setup_rollup_db(&mut ru_db).unwrap();
100
101 let ru_db = Arc::new(ru_db);
102
103 RollupEnv::new(ru_db, TEST_SYS, &TestCfg, &NoopBlock)
104}
105
106pub fn host_sim_env() -> HostEnv<Arc<InMemoryDB>, NoOpInspector> {
108 let mut host_db = InMemoryDB::default();
109 setup_host_db(&mut host_db).unwrap();
110 let host_db = Arc::new(host_db);
111
112 HostEnv::new(host_db, TEST_SYS, &HostTestCfg, &NoopBlock)
113}
114
115#[derive(Clone)]
120pub struct SyncAsyncSource(pub Arc<InMemoryDB>);
121
122impl StateSource for SyncAsyncSource {
123 type Error = <InMemoryDB as trevm::revm::DatabaseRef>::Error;
124
125 async fn account_details(&self, address: &Address) -> Result<AcctInfo, Self::Error> {
126 use trevm::revm::DatabaseRef;
127 let info = self.0.basic_ref(*address)?.unwrap_or_default();
128 let has_code = info.code_hash() != trevm::revm::primitives::KECCAK_EMPTY;
129 Ok(AcctInfo { nonce: info.nonce, balance: info.balance, has_code })
130 }
131}
132
133pub fn test_sim_env(
135 deadline: tokio::time::Instant,
136) -> BlockBuild<Arc<InMemoryDB>, Arc<InMemoryDB>, SyncAsyncSource, SyncAsyncSource> {
137 let ru_evm = rollup_sim_env();
138 let host_evm = host_sim_env();
139
140 let mut ru_async_db = InMemoryDB::default();
141 setup_rollup_db(&mut ru_async_db).unwrap();
142 let mut host_async_db = InMemoryDB::default();
143 setup_host_db(&mut host_async_db).unwrap();
144
145 BlockBuild::new(
146 ru_evm,
147 host_evm,
148 deadline,
149 10,
150 Default::default(),
151 50_000_000,
152 50_000_000,
153 SyncAsyncSource(Arc::new(ru_async_db)),
154 SyncAsyncSource(Arc::new(host_async_db)),
155 )
156}
157
158fn modify_account<Db, F>(db: &mut Db, addr: Address, f: F) -> Result<AccountInfo, Db::Error>
159where
160 F: FnOnce(&mut AccountInfo),
161 Db: Database + DatabaseCommit,
162{
163 let mut acct: AccountInfo = db.basic(addr)?.unwrap_or_default();
164 let old = acct.clone();
165 f(&mut acct);
166
167 let mut acct: Account = acct.into();
168 acct.mark_touch();
169
170 let changes: EvmState = [(addr, acct)].into_iter().collect();
171 db.commit(changes);
172 Ok(old)
173}
174
175fn set_bytecode_at<Db: Database + DatabaseCommit>(
177 db: &mut Db,
178 addr: Address,
179 code: Bytes,
180) -> Result<(), Db::Error> {
181 modify_account(db, addr, |acct| {
182 acct.set_code(Bytecode::new_legacy(code));
183 })
184 .map(|_| ())
185 .inspect(|_| {
186 assert_ne!(db.basic(addr).unwrap().unwrap().code_hash, KECCAK256_EMPTY);
187 })
188}
189
190fn set_balance_of<Db: Database + DatabaseCommit>(
191 db: &mut Db,
192 addr: Address,
193 balance: U256,
194) -> Result<(), Db::Error> {
195 modify_account(db, addr, |acct| {
196 acct.balance = balance;
197 })
198 .map(|_| ())
199 .inspect(|_| {
200 assert_eq!(db.basic(addr).unwrap().unwrap().balance, balance);
201 })
202}
203
204fn set_storage_at<Db: Database + DatabaseCommit>(
205 db: &mut Db,
206 addr: Address,
207 slot: U256,
208 value: U256,
209) -> Result<(), Db::Error> {
210 let mut account: Account = db.basic(addr)?.unwrap_or_default().into();
211 let mut changes = EvmState::default();
212 account.storage.insert(slot, EvmStorageSlot::new(value, 1));
213 account.mark_touch();
214 changes.insert(addr, account);
215 db.commit(changes);
216 assert_eq!(db.storage(addr, slot).unwrap(), value);
217 Ok(())
218}
219
220fn setup_db<Db: Database + DatabaseCommit>(db: &mut Db, rollup: bool) -> Result<(), Db::Error> {
221 let (weth, wbtc, orders, orders_bytecode, passage, passage_bytecode);
222 if rollup {
223 weth = RU_WETH;
224 wbtc = RU_WBTC;
225 orders = TEST_SYS.ru_orders();
226 orders_bytecode = RU_ORDERS_BYTECODE;
227 passage = TEST_SYS.ru_passage();
228 passage_bytecode = RU_PASSAGE_BYTECODE;
229 } else {
230 weth = HOST_WETH;
231 wbtc = HOST_WBTC;
232 orders = TEST_SYS.host_orders();
233 orders_bytecode = HOST_ORDERS_BYTECODE;
234 passage = TEST_SYS.host_passage();
235 passage_bytecode = HOST_PASSAGE_BYTECODE;
236 }
237
238 deploy_weth_at(db, weth)?;
240 deploy_wbtc_at(db, wbtc)?;
241
242 set_bytecode_at(db, orders, orders_bytecode)?;
244 set_bytecode_at(db, passage, passage_bytecode)?;
245
246 set_bytecode_at(db, COUNTER_TEST_ADDRESS, COUNTER_BYTECODE)?;
247
248 set_bytecode_at(db, REVERT_TEST_ADDRESS, REVERT_BYTECODE)?;
250
251 let max_approve = U256::MAX;
252 let token_balance = U256::from(1000 * ETH_TO_WEI);
253
254 TEST_USERS.iter().copied().for_each(|user| {
256 set_balance_of(db, user, U256::from(1000 * ETH_TO_WEI)).unwrap();
257
258 set_storage_at(db, weth, balance_slot_for(user), token_balance).unwrap();
259 set_storage_at(db, weth, allowances_slot_for(user, orders), max_approve).unwrap();
260
261 set_storage_at(db, wbtc, balance_slot_for(user), token_balance).unwrap();
262 set_storage_at(db, wbtc, allowances_slot_for(user, orders), max_approve).unwrap();
263 });
264
265 Ok(())
266}
267
268fn setup_rollup_db<Db: Database + DatabaseCommit>(db: &mut Db) -> Result<(), Db::Error> {
269 setup_db(db, true)
270}
271
272fn setup_host_db<Db: Database + DatabaseCommit>(db: &mut Db) -> Result<(), Db::Error> {
273 setup_db(db, false)
274}