1use crate::primitives::{Address, Bytes, Env, Log, B256, U256};
2use core::ops::{Deref, DerefMut};
3
4mod dummy;
5pub use dummy::DummyHost;
6
7pub trait Host {
9 fn env(&self) -> &Env;
11
12 fn env_mut(&mut self) -> &mut Env;
14
15 fn load_account_delegated(&mut self, address: Address) -> Option<AccountLoad>;
17
18 fn block_hash(&mut self, number: u64) -> Option<B256>;
20
21 fn balance(&mut self, address: Address) -> Option<StateLoad<U256>>;
23
24 fn code(&mut self, address: Address) -> Option<Eip7702CodeLoad<Bytes>>;
26
27 fn code_hash(&mut self, address: Address) -> Option<Eip7702CodeLoad<B256>>;
29
30 fn sload(&mut self, address: Address, index: U256) -> Option<StateLoad<U256>>;
32
33 fn sstore(
37 &mut self,
38 address: Address,
39 index: U256,
40 value: U256,
41 ) -> Option<StateLoad<SStoreResult>>;
42
43 fn tload(&mut self, address: Address, index: U256) -> U256;
45
46 fn tstore(&mut self, address: Address, index: U256, value: U256);
48
49 fn log(&mut self, log: Log);
51
52 fn selfdestruct(
54 &mut self,
55 address: Address,
56 target: Address,
57 ) -> Option<StateLoad<SelfDestructResult>>;
58}
59
60#[derive(Clone, Debug, Default, PartialEq, Eq)]
62#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
63pub struct SStoreResult {
64 pub original_value: U256,
66 pub present_value: U256,
68 pub new_value: U256,
70}
71
72impl SStoreResult {
73 #[inline]
75 pub fn is_new_eq_present(&self) -> bool {
76 self.new_value == self.present_value
77 }
78
79 #[inline]
81 pub fn is_original_eq_present(&self) -> bool {
82 self.original_value == self.present_value
83 }
84
85 #[inline]
87 pub fn is_original_eq_new(&self) -> bool {
88 self.original_value == self.new_value
89 }
90
91 #[inline]
93 pub fn is_original_zero(&self) -> bool {
94 self.original_value.is_zero()
95 }
96
97 #[inline]
99 pub fn is_present_zero(&self) -> bool {
100 self.present_value.is_zero()
101 }
102
103 #[inline]
105 pub fn is_new_zero(&self) -> bool {
106 self.new_value.is_zero()
107 }
108}
109
110#[derive(Clone, Debug, Default, PartialEq, Eq)]
112#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
113pub struct AccountLoad {
114 pub load: Eip7702CodeLoad<()>,
116 pub is_empty: bool,
118}
119
120impl Deref for AccountLoad {
121 type Target = Eip7702CodeLoad<()>;
122
123 fn deref(&self) -> &Self::Target {
124 &self.load
125 }
126}
127
128impl DerefMut for AccountLoad {
129 fn deref_mut(&mut self) -> &mut Self::Target {
130 &mut self.load
131 }
132}
133
134#[derive(Clone, Debug, Default, PartialEq, Eq)]
136#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
137pub struct StateLoad<T> {
138 pub data: T,
140 pub is_cold: bool,
142}
143
144impl<T> Deref for StateLoad<T> {
145 type Target = T;
146
147 fn deref(&self) -> &Self::Target {
148 &self.data
149 }
150}
151
152impl<T> DerefMut for StateLoad<T> {
153 fn deref_mut(&mut self) -> &mut Self::Target {
154 &mut self.data
155 }
156}
157
158impl<T> StateLoad<T> {
159 pub fn new(data: T, is_cold: bool) -> Self {
161 Self { data, is_cold }
162 }
163
164 pub fn map<B, F>(self, f: F) -> StateLoad<B>
168 where
169 F: FnOnce(T) -> B,
170 {
171 StateLoad::new(f(self.data), self.is_cold)
172 }
173}
174
175#[derive(Clone, Debug, Default, PartialEq, Eq)]
179#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
180pub struct Eip7702CodeLoad<T> {
181 pub state_load: StateLoad<T>,
183 pub is_delegate_account_cold: Option<bool>,
185}
186
187impl<T> Deref for Eip7702CodeLoad<T> {
188 type Target = StateLoad<T>;
189
190 fn deref(&self) -> &Self::Target {
191 &self.state_load
192 }
193}
194
195impl<T> DerefMut for Eip7702CodeLoad<T> {
196 fn deref_mut(&mut self) -> &mut Self::Target {
197 &mut self.state_load
198 }
199}
200
201impl<T> Eip7702CodeLoad<T> {
202 pub fn new_state_load(state_load: StateLoad<T>) -> Self {
204 Self {
205 state_load,
206 is_delegate_account_cold: None,
207 }
208 }
209
210 pub fn new_not_delegated(data: T, is_cold: bool) -> Self {
212 Self {
213 state_load: StateLoad::new(data, is_cold),
214 is_delegate_account_cold: None,
215 }
216 }
217
218 pub fn into_components(self) -> (T, Eip7702CodeLoad<()>) {
221 let is_cold = self.is_cold;
222 (
223 self.state_load.data,
224 Eip7702CodeLoad {
225 state_load: StateLoad::new((), is_cold),
226 is_delegate_account_cold: self.is_delegate_account_cold,
227 },
228 )
229 }
230
231 pub fn set_delegate_load(&mut self, is_delegate_account_cold: bool) {
233 self.is_delegate_account_cold = Some(is_delegate_account_cold);
234 }
235
236 pub fn new(state_load: StateLoad<T>, is_delegate_account_cold: bool) -> Self {
238 Self {
239 state_load,
240 is_delegate_account_cold: Some(is_delegate_account_cold),
241 }
242 }
243}
244
245#[derive(Clone, Debug, Default, PartialEq, Eq, Hash)]
249#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
250pub struct SelfDestructResult {
251 pub had_value: bool,
252 pub target_exists: bool,
253 pub previously_destroyed: bool,
254}
255
256#[cfg(test)]
257mod tests {
258 use super::*;
259
260 fn assert_host<H: Host + ?Sized>() {}
261
262 #[test]
263 fn object_safety() {
264 assert_host::<DummyHost>();
265 assert_host::<dyn Host>();
266 }
267}