foundry_evm_symbolic/runtime/
executor_view.rs1use super::*;
2use foundry_evm::core::backend::DatabaseError;
3
4pub struct ExecutorView<'a> {
9 pub(crate) backend: &'a dyn DatabaseRef<Error = DatabaseError>,
10 pub(crate) spec_id: SpecId,
11 pub(crate) chain_id: u64,
12 pub(crate) memory_limit: u64,
13 pub(crate) max_code_size: usize,
14 pub(crate) active_fork_id: Option<U256>,
15 pub(crate) account_addresses: Vec<Address>,
17 pub(crate) block: ExecutorBlock,
18 pub(crate) gas_price: u128,
19 pub(crate) isolate: bool,
20 pub(crate) internal_expect_revert: bool,
22 pub(crate) blob_hashes: Vec<B256>,
23 pub(crate) arbitrary_storage_targets: Vec<(Address, bool)>,
24 pub(crate) arbitrary_storage_copies: Vec<(Address, Address)>,
25 pub(crate) storage_load_hooks: Vec<(Address, SymbolicStorageHook)>,
26 pub(crate) storage_store_hooks: Vec<(Address, SymbolicStorageHook)>,
27 pub(crate) mapping_storage_store_hooks: Vec<((Address, U256), SymbolicStorageHook)>,
28}
29
30pub(crate) struct ExecutorBlock {
32 pub(crate) coinbase: Address,
33 pub(crate) timestamp: U256,
34 pub(crate) number: U256,
35 pub(crate) difficulty: U256,
36 pub(crate) gas_limit: u64,
37 pub(crate) basefee: u64,
38 pub(crate) blob_basefee: u128,
39}
40
41impl<'a> ExecutorView<'a> {
42 pub fn new<FEN: FoundryEvmNetwork>(executor: &'a Executor<FEN>) -> Self {
44 let backend = executor.backend();
45 let evm_env = executor.evm_env();
46 let cheats = executor.inspector().cheatcodes.as_deref();
47 let block = cheats.and_then(|cheats| cheats.block.as_ref()).unwrap_or(evm_env.block_env());
48 let difficulty = block.prevrandao().map(Into::into).unwrap_or_else(|| block.difficulty());
49
50 let mut account_addresses =
51 backend.mem_db().cache.accounts.keys().copied().collect::<Vec<_>>();
52 if let Some(db) = backend.active_fork_db() {
53 account_addresses.extend(db.cache.accounts.keys().copied());
54 }
55
56 Self {
57 backend,
58 spec_id: executor.spec_id().into(),
59 chain_id: evm_env.cfg_env.chain_id,
60 memory_limit: evm_env.cfg_env.memory_limit(),
61 max_code_size: evm_env.cfg_env.max_code_size(),
62 active_fork_id: backend.active_fork_id(),
63 account_addresses,
64 block: ExecutorBlock {
65 coinbase: block.beneficiary(),
66 timestamp: block.timestamp(),
67 number: block.number(),
68 difficulty,
69 gas_limit: block.gas_limit(),
70 basefee: block.basefee(),
71 blob_basefee: block.blob_gasprice().unwrap_or_default(),
72 },
73 gas_price: cheats
74 .and_then(|cheats| cheats.gas_price)
75 .unwrap_or_else(|| executor.tx_env().gas_price()),
76 isolate: cheats.is_some_and(|cheats| cheats.core.config.isolate),
77 internal_expect_revert: cheats
78 .is_some_and(|cheats| cheats.core.config.internal_expect_revert),
79 blob_hashes: executor.tx_env().blob_versioned_hashes().to_vec(),
80 arbitrary_storage_targets: cheats
81 .into_iter()
82 .flat_map(|cheats| cheats.arbitrary_storage_target_overwrite_modes())
83 .collect(),
84 arbitrary_storage_copies: cheats
85 .into_iter()
86 .flat_map(|cheats| cheats.arbitrary_storage_copied_target_sources())
87 .collect(),
88 storage_load_hooks: cheats
89 .into_iter()
90 .flat_map(|cheats| cheats.storage_load_hooks())
91 .map(|(target, hook)| {
92 (
93 target,
94 SymbolicStorageHook {
95 callback_target: hook.callback_target,
96 callback_selector: hook.callback_selector,
97 },
98 )
99 })
100 .collect(),
101 storage_store_hooks: cheats
102 .into_iter()
103 .flat_map(|cheats| cheats.storage_store_hooks())
104 .map(|(target, hook)| {
105 (
106 target,
107 SymbolicStorageHook {
108 callback_target: hook.callback_target,
109 callback_selector: hook.callback_selector,
110 },
111 )
112 })
113 .collect(),
114 mapping_storage_store_hooks: cheats
115 .into_iter()
116 .flat_map(|cheats| cheats.mapping_storage_store_hooks())
117 .map(|(target, root, hook)| {
118 (
119 (target, root.into()),
120 SymbolicStorageHook {
121 callback_target: hook.callback_target,
122 callback_selector: hook.callback_selector,
123 },
124 )
125 })
126 .collect(),
127 }
128 }
129}