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