tycho_simulation/evm/engine_db/
mod.rs1use std::{collections::HashMap, fmt::Debug};
2
3use alloy::primitives::{Address, U160};
4use revm::{primitives::KECCAK_EMPTY, state::AccountInfo, DatabaseRef};
5use tycho_client::feed::BlockHeader;
6use tycho_common::simulation::errors::SimulationError;
7
8use crate::evm::{
9 engine_db::{
10 engine_db_interface::EngineDatabaseInterface,
11 tycho_db::{PreCachedDB, PreCachedDBError},
12 },
13 simulation::SimulationEngine,
14 tycho_models::{AccountUpdate, ChangeType, ResponseAccount},
15};
16
17pub mod engine_db_interface;
18pub mod simulation_db;
19pub mod tycho_db;
20pub mod utils;
21
22pub static SHARED_TYCHO_DB: std::sync::LazyLock<PreCachedDB> = std::sync::LazyLock::new(|| {
23 PreCachedDB::new().unwrap_or_else(|err| panic!("Failed to create PreCachedDB: {err}"))
24});
25
26pub fn create_engine<D: EngineDatabaseInterface + Clone + Debug>(
33 db: D,
34 trace: bool,
35) -> Result<SimulationEngine<D>, SimulationError>
36where
37 <D as EngineDatabaseInterface>::Error: Debug,
38 <D as DatabaseRef>::Error: Debug,
39{
40 let engine = SimulationEngine::new(db.clone(), trace);
41
42 let zero_account_info =
43 AccountInfo { balance: Default::default(), nonce: 0, code_hash: KECCAK_EMPTY, code: None };
44
45 engine
47 .state
48 .init_account(Address::ZERO, zero_account_info.clone(), None, false)
49 .map_err(|e| {
50 SimulationError::FatalError(format!("Failed to init zero address: {:?}", e))
51 })?;
52
53 engine
54 .state
55 .init_account(Address::from(U160::from(4)), zero_account_info.clone(), None, false)
56 .map_err(|e| {
57 SimulationError::FatalError(format!(
58 "Failed to init ecrecover precompile address: {:?}",
59 e
60 ))
61 })?;
62
63 Ok(engine)
64}
65
66pub fn update_engine(
67 db: PreCachedDB,
68 block: Option<BlockHeader>,
69 vm_storage: Option<HashMap<Address, ResponseAccount>>,
70 account_updates: HashMap<Address, AccountUpdate>,
71) -> Result<Vec<AccountUpdate>, PreCachedDBError> {
72 if let Some(block) = block {
73 let mut vm_updates: Vec<AccountUpdate> = Vec::new();
74
75 for account_update in account_updates.values() {
76 vm_updates.push(account_update.clone());
77 }
78
79 if let Some(vm_storage_values) = vm_storage {
80 for vm_storage_values in vm_storage_values.values() {
81 vm_updates.push(AccountUpdate {
83 address: vm_storage_values.address,
84 chain: vm_storage_values.chain,
85 slots: vm_storage_values.slots.clone(),
86 balance: Some(vm_storage_values.native_balance),
87 code: Some(vm_storage_values.code.clone()),
88 change: ChangeType::Creation,
89 });
90 }
91 }
92
93 if !vm_updates.is_empty() {
94 db.update(vm_updates.clone(), Some(block))?;
95 }
96
97 Ok(vm_updates)
98 } else {
99 Ok(vec![])
100 }
101}