use std::sync::Arc;
use crate::{
contracts::{
counter::{COUNTER_BYTECODE, COUNTER_TEST_ADDRESS},
reverts::{REVERT_BYTECODE, REVERT_TEST_ADDRESS},
system::{
HOST_ORDERS_BYTECODE, HOST_PASSAGE_BYTECODE, RU_ORDERS_BYTECODE, RU_PASSAGE_BYTECODE,
},
token::{allowances_slot_for, balance_slot_for, deploy_wbtc_at, deploy_weth_at},
},
users::TEST_USERS,
};
use alloy::{
consensus::constants::ETH_TO_WEI,
primitives::{Address, Bytes, KECCAK256_EMPTY, U256},
};
use signet_constants::test_utils::*;
use signet_sim::{BlockBuild, HostEnv, RollupEnv};
use trevm::{
helpers::Ctx,
revm::{
context::CfgEnv,
database::in_memory_db::InMemoryDB,
inspector::NoOpInspector,
primitives::hardfork::SpecId,
state::{Account, AccountInfo, Bytecode, EvmState, EvmStorageSlot},
Database, DatabaseCommit, Inspector,
},
Cfg, NoopBlock,
};
pub fn test_signet_evm() -> signet_evm::EvmNeedsBlock<InMemoryDB> {
test_signet_evm_with_inspector(NoOpInspector)
}
pub fn test_signet_evm_with_inspector<I>(inspector: I) -> signet_evm::EvmNeedsBlock<InMemoryDB, I>
where
I: Inspector<Ctx<InMemoryDB>>,
{
let mut db = InMemoryDB::default();
setup_rollup_db(&mut db).unwrap();
signet_evm::signet_evm_with_inspector(db, inspector, TEST_SYS).fill_cfg(&TestCfg)
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub struct TestCfg;
impl Cfg for TestCfg {
fn fill_cfg_env(&self, cfg_env: &mut CfgEnv) {
let CfgEnv { chain_id, spec, .. } = cfg_env;
*chain_id = RU_CHAIN_ID;
*spec = SpecId::default();
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub struct HostTestCfg;
impl Cfg for HostTestCfg {
fn fill_cfg_env(&self, cfg_env: &mut CfgEnv) {
let CfgEnv { chain_id, spec, .. } = cfg_env;
*chain_id = HOST_CHAIN_ID;
*spec = SpecId::default();
}
}
pub fn rollup_sim_env() -> RollupEnv<Arc<InMemoryDB>, NoOpInspector> {
let mut ru_db = InMemoryDB::default();
setup_rollup_db(&mut ru_db).unwrap();
let ru_db = Arc::new(ru_db);
RollupEnv::new(ru_db, TEST_SYS, &TestCfg, &NoopBlock)
}
pub fn host_sim_env() -> HostEnv<Arc<InMemoryDB>, NoOpInspector> {
let mut host_db = InMemoryDB::default();
setup_host_db(&mut host_db).unwrap();
let host_db = Arc::new(host_db);
HostEnv::new(host_db, TEST_SYS, &HostTestCfg, &NoopBlock)
}
pub fn test_sim_env(deadline: std::time::Instant) -> BlockBuild<Arc<InMemoryDB>, Arc<InMemoryDB>> {
let (ru_evm, host_evm) = (rollup_sim_env(), host_sim_env());
BlockBuild::new(ru_evm, host_evm, deadline, 10, Default::default(), 50_000_000, 50_000_000)
}
fn modify_account<Db, F>(db: &mut Db, addr: Address, f: F) -> Result<AccountInfo, Db::Error>
where
F: FnOnce(&mut AccountInfo),
Db: Database + DatabaseCommit,
{
let mut acct: AccountInfo = db.basic(addr)?.unwrap_or_default();
let old = acct.clone();
f(&mut acct);
let mut acct: Account = acct.into();
acct.mark_touch();
let changes: EvmState = [(addr, acct)].into_iter().collect();
db.commit(changes);
Ok(old)
}
fn set_bytecode_at<Db: Database + DatabaseCommit>(
db: &mut Db,
addr: Address,
code: Bytes,
) -> Result<(), Db::Error> {
modify_account(db, addr, |acct| {
acct.set_code(Bytecode::new_legacy(code));
})
.map(|_| ())
.inspect(|_| {
assert_ne!(db.basic(addr).unwrap().unwrap().code_hash, KECCAK256_EMPTY);
})
}
fn set_balance_of<Db: Database + DatabaseCommit>(
db: &mut Db,
addr: Address,
balance: U256,
) -> Result<(), Db::Error> {
modify_account(db, addr, |acct| {
acct.balance = balance;
})
.map(|_| ())
.inspect(|_| {
assert_eq!(db.basic(addr).unwrap().unwrap().balance, balance);
})
}
fn set_storage_at<Db: Database + DatabaseCommit>(
db: &mut Db,
addr: Address,
slot: U256,
value: U256,
) -> Result<(), Db::Error> {
let mut account: Account = db.basic(addr)?.unwrap_or_default().into();
let mut changes = EvmState::default();
account.storage.insert(slot, EvmStorageSlot::new(value, 1));
account.mark_touch();
changes.insert(addr, account);
db.commit(changes);
assert_eq!(db.storage(addr, slot).unwrap(), value);
Ok(())
}
fn setup_db<Db: Database + DatabaseCommit>(db: &mut Db, rollup: bool) -> Result<(), Db::Error> {
let (weth, wbtc, orders, orders_bytecode, passage, passage_bytecode);
if rollup {
weth = RU_WETH;
wbtc = RU_WBTC;
orders = TEST_SYS.ru_orders();
orders_bytecode = RU_ORDERS_BYTECODE;
passage = TEST_SYS.ru_passage();
passage_bytecode = RU_PASSAGE_BYTECODE;
} else {
weth = HOST_WETH;
wbtc = HOST_WBTC;
orders = TEST_SYS.host_orders();
orders_bytecode = HOST_ORDERS_BYTECODE;
passage = TEST_SYS.host_passage();
passage_bytecode = HOST_PASSAGE_BYTECODE;
}
deploy_weth_at(db, weth)?;
deploy_wbtc_at(db, wbtc)?;
set_bytecode_at(db, orders, orders_bytecode)?;
set_bytecode_at(db, passage, passage_bytecode)?;
set_bytecode_at(db, COUNTER_TEST_ADDRESS, COUNTER_BYTECODE)?;
set_bytecode_at(db, REVERT_TEST_ADDRESS, REVERT_BYTECODE)?;
let max_approve = U256::MAX;
let token_balance = U256::from(1000 * ETH_TO_WEI);
TEST_USERS.iter().copied().for_each(|user| {
set_balance_of(db, user, U256::from(1000 * ETH_TO_WEI)).unwrap();
set_storage_at(db, weth, balance_slot_for(user), token_balance).unwrap();
set_storage_at(db, weth, allowances_slot_for(user, orders), max_approve).unwrap();
set_storage_at(db, wbtc, balance_slot_for(user), token_balance).unwrap();
set_storage_at(db, wbtc, allowances_slot_for(user, orders), max_approve).unwrap();
});
Ok(())
}
fn setup_rollup_db<Db: Database + DatabaseCommit>(db: &mut Db) -> Result<(), Db::Error> {
setup_db(db, true)
}
fn setup_host_db<Db: Database + DatabaseCommit>(db: &mut Db) -> Result<(), Db::Error> {
setup_db(db, false)
}