1use crate::{
4 cfg::GasParams,
5 context::{SStoreResult, SelfDestructResult, StateLoad},
6 journaled_state::{AccountInfoLoad, AccountLoad},
7};
8use auto_impl::auto_impl;
9use primitives::{hardfork::SpecId, Address, Bytes, Log, StorageKey, StorageValue, B256, U256};
10use state::Bytecode;
11
12#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)]
14#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
15pub enum LoadError {
16 DBError,
18 ColdLoadSkipped,
20}
21
22#[auto_impl(&mut, Box)]
28pub trait Host {
29 fn basefee(&self) -> U256;
33 fn blob_gasprice(&self) -> U256;
35 fn gas_limit(&self) -> U256;
37 fn difficulty(&self) -> U256;
39 fn prevrandao(&self) -> Option<U256>;
41 fn block_number(&self) -> U256;
43 fn timestamp(&self) -> U256;
45 fn beneficiary(&self) -> Address;
47 fn slot_num(&self) -> U256;
49 fn chain_id(&self) -> U256;
51
52 fn effective_gas_price(&self) -> U256;
56 fn caller(&self) -> Address;
58 fn blob_hash(&self, number: usize) -> Option<U256>;
60
61 fn max_initcode_size(&self) -> usize;
65
66 fn gas_params(&self) -> &GasParams;
68
69 fn is_amsterdam_eip8037_enabled(&self) -> bool;
71
72 fn block_hash(&mut self, number: u64) -> Option<B256>;
76
77 fn selfdestruct(
81 &mut self,
82 address: Address,
83 target: Address,
84 skip_cold_load: bool,
85 ) -> Result<StateLoad<SelfDestructResult>, LoadError>;
86
87 fn log(&mut self, log: Log);
89
90 fn sstore_skip_cold_load(
92 &mut self,
93 address: Address,
94 key: StorageKey,
95 value: StorageValue,
96 skip_cold_load: bool,
97 ) -> Result<StateLoad<SStoreResult>, LoadError>;
98
99 fn sstore(
101 &mut self,
102 address: Address,
103 key: StorageKey,
104 value: StorageValue,
105 ) -> Option<StateLoad<SStoreResult>> {
106 self.sstore_skip_cold_load(address, key, value, false).ok()
107 }
108
109 fn sload_skip_cold_load(
111 &mut self,
112 address: Address,
113 key: StorageKey,
114 skip_cold_load: bool,
115 ) -> Result<StateLoad<StorageValue>, LoadError>;
116
117 fn sload(&mut self, address: Address, key: StorageKey) -> Option<StateLoad<StorageValue>> {
119 self.sload_skip_cold_load(address, key, false).ok()
120 }
121
122 fn tstore(&mut self, address: Address, key: StorageKey, value: StorageValue);
124
125 fn tload(&mut self, address: Address, key: StorageKey) -> StorageValue;
127
128 fn load_account_info_skip_cold_load(
137 &mut self,
138 address: Address,
139 load_code: bool,
140 skip_cold_load: bool,
141 ) -> Result<AccountInfoLoad<'_>, LoadError>;
142
143 #[inline]
145 fn balance(&mut self, address: Address) -> Option<StateLoad<U256>> {
146 self.load_account_info_skip_cold_load(address, false, false)
147 .ok()
148 .map(|load| load.into_state_load(|i| i.balance))
149 }
150
151 #[inline]
153 fn load_account_delegated(&mut self, address: Address) -> Option<StateLoad<AccountLoad>> {
154 let account = self
155 .load_account_info_skip_cold_load(address, true, false)
156 .ok()?;
157
158 let mut account_load = StateLoad::new(
159 AccountLoad {
160 is_delegate_account_cold: None,
161 is_empty: account.is_empty,
162 },
163 account.is_cold,
164 );
165
166 if let Some(address) = account.code.as_ref().and_then(Bytecode::eip7702_address) {
168 let delegate_account = self
169 .load_account_info_skip_cold_load(address, true, false)
170 .ok()?;
171 account_load.data.is_delegate_account_cold = Some(delegate_account.is_cold);
172 account_load.data.is_empty = delegate_account.is_empty;
173 }
174
175 Some(account_load)
176 }
177
178 #[inline]
180 fn load_account_code(&mut self, address: Address) -> Option<StateLoad<Bytes>> {
181 self.load_account_info_skip_cold_load(address, true, false)
182 .ok()
183 .map(|load| {
184 load.into_state_load(|i| {
185 i.code
186 .as_ref()
187 .map(|b| b.original_bytes())
188 .unwrap_or_default()
189 })
190 })
191 }
192
193 #[inline]
195 fn load_account_code_hash(&mut self, address: Address) -> Option<StateLoad<B256>> {
196 self.load_account_info_skip_cold_load(address, false, false)
197 .ok()
198 .map(|load| {
199 load.into_state_load(|i| {
200 if i.is_empty() {
201 B256::ZERO
202 } else {
203 i.code_hash
204 }
205 })
206 })
207 }
208}
209
210#[derive(Default, Debug)]
212pub struct DummyHost {
213 gas_params: GasParams,
214}
215
216impl DummyHost {
217 pub fn new(spec: SpecId) -> Self {
219 Self {
220 gas_params: GasParams::new_spec(spec),
221 }
222 }
223}
224
225impl Host for DummyHost {
226 fn basefee(&self) -> U256 {
227 U256::ZERO
228 }
229
230 fn blob_gasprice(&self) -> U256 {
231 U256::ZERO
232 }
233
234 fn gas_limit(&self) -> U256 {
235 U256::ZERO
236 }
237
238 fn gas_params(&self) -> &GasParams {
239 &self.gas_params
240 }
241
242 fn is_amsterdam_eip8037_enabled(&self) -> bool {
243 false
244 }
245
246 fn difficulty(&self) -> U256 {
247 U256::ZERO
248 }
249
250 fn prevrandao(&self) -> Option<U256> {
251 None
252 }
253
254 fn block_number(&self) -> U256 {
255 U256::ZERO
256 }
257
258 fn timestamp(&self) -> U256 {
259 U256::ZERO
260 }
261
262 fn beneficiary(&self) -> Address {
263 Address::ZERO
264 }
265
266 fn slot_num(&self) -> U256 {
267 U256::ZERO
268 }
269
270 fn chain_id(&self) -> U256 {
271 U256::ZERO
272 }
273
274 fn effective_gas_price(&self) -> U256 {
275 U256::ZERO
276 }
277
278 fn caller(&self) -> Address {
279 Address::ZERO
280 }
281
282 fn blob_hash(&self, _number: usize) -> Option<U256> {
283 None
284 }
285
286 fn max_initcode_size(&self) -> usize {
287 0
288 }
289
290 fn block_hash(&mut self, _number: u64) -> Option<B256> {
291 None
292 }
293
294 fn selfdestruct(
295 &mut self,
296 _address: Address,
297 _target: Address,
298 _skip_cold_load: bool,
299 ) -> Result<StateLoad<SelfDestructResult>, LoadError> {
300 Ok(Default::default())
301 }
302
303 fn log(&mut self, _log: Log) {}
304
305 fn tstore(&mut self, _address: Address, _key: StorageKey, _value: StorageValue) {}
306
307 fn tload(&mut self, _address: Address, _key: StorageKey) -> StorageValue {
308 StorageValue::ZERO
309 }
310
311 fn load_account_info_skip_cold_load(
312 &mut self,
313 _address: Address,
314 _load_code: bool,
315 _skip_cold_load: bool,
316 ) -> Result<AccountInfoLoad<'_>, LoadError> {
317 Ok(Default::default())
318 }
319
320 fn sstore_skip_cold_load(
321 &mut self,
322 _address: Address,
323 _key: StorageKey,
324 _value: StorageValue,
325 _skip_cold_load: bool,
326 ) -> Result<StateLoad<SStoreResult>, LoadError> {
327 Ok(Default::default())
328 }
329
330 fn sload_skip_cold_load(
331 &mut self,
332 _address: Address,
333 _key: StorageKey,
334 _skip_cold_load: bool,
335 ) -> Result<StateLoad<StorageValue>, LoadError> {
336 Ok(Default::default())
337 }
338}