revm_interpreter/
host.rs

1use crate::primitives::{Address, Bytes, Env, Log, B256, U256};
2use core::ops::{Deref, DerefMut};
3
4mod dummy;
5pub use dummy::DummyHost;
6
7/// EVM context host.
8pub trait Host {
9    /// Returns a reference to the environment.
10    fn env(&self) -> &Env;
11
12    /// Returns a mutable reference to the environment.
13    fn env_mut(&mut self) -> &mut Env;
14
15    /// Load an account code.
16    fn load_account_delegated(&mut self, address: Address) -> Option<AccountLoad>;
17
18    /// Get the block hash of the given block `number`.
19    fn block_hash(&mut self, number: u64) -> Option<B256>;
20
21    /// Get balance of `address` and if the account is cold.
22    fn balance(&mut self, address: Address) -> Option<StateLoad<U256>>;
23
24    /// Get code of `address` and if the account is cold.
25    fn code(&mut self, address: Address) -> Option<Eip7702CodeLoad<Bytes>>;
26
27    /// Get code hash of `address` and if the account is cold.
28    fn code_hash(&mut self, address: Address) -> Option<Eip7702CodeLoad<B256>>;
29
30    /// Get storage value of `address` at `index` and if the account is cold.
31    fn sload(&mut self, address: Address, index: U256) -> Option<StateLoad<U256>>;
32
33    /// Set storage value of account address at index.
34    ///
35    /// Returns [`StateLoad`] with [`SStoreResult`] that contains original/new/old storage value.
36    fn sstore(
37        &mut self,
38        address: Address,
39        index: U256,
40        value: U256,
41    ) -> Option<StateLoad<SStoreResult>>;
42
43    /// Get the transient storage value of `address` at `index`.
44    fn tload(&mut self, address: Address, index: U256) -> U256;
45
46    /// Set the transient storage value of `address` at `index`.
47    fn tstore(&mut self, address: Address, index: U256, value: U256);
48
49    /// Emit a log owned by `address` with given `LogData`.
50    fn log(&mut self, log: Log);
51
52    /// Mark `address` to be deleted, with funds transferred to `target`.
53    fn selfdestruct(
54        &mut self,
55        address: Address,
56        target: Address,
57    ) -> Option<StateLoad<SelfDestructResult>>;
58}
59
60/// Represents the result of an `sstore` operation.
61#[derive(Clone, Debug, Default, PartialEq, Eq)]
62#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
63pub struct SStoreResult {
64    /// Value of the storage when it is first read
65    pub original_value: U256,
66    /// Current value of the storage
67    pub present_value: U256,
68    /// New value that is set
69    pub new_value: U256,
70}
71
72impl SStoreResult {
73    /// Returns `true` if the new value is equal to the present value.
74    #[inline]
75    pub fn is_new_eq_present(&self) -> bool {
76        self.new_value == self.present_value
77    }
78
79    /// Returns `true` if the original value is equal to the present value.
80    #[inline]
81    pub fn is_original_eq_present(&self) -> bool {
82        self.original_value == self.present_value
83    }
84
85    /// Returns `true` if the original value is equal to the new value.
86    #[inline]
87    pub fn is_original_eq_new(&self) -> bool {
88        self.original_value == self.new_value
89    }
90
91    /// Returns `true` if the original value is zero.
92    #[inline]
93    pub fn is_original_zero(&self) -> bool {
94        self.original_value.is_zero()
95    }
96
97    /// Returns `true` if the present value is zero.
98    #[inline]
99    pub fn is_present_zero(&self) -> bool {
100        self.present_value.is_zero()
101    }
102
103    /// Returns `true` if the new value is zero.
104    #[inline]
105    pub fn is_new_zero(&self) -> bool {
106        self.new_value.is_zero()
107    }
108}
109
110/// Result of the account load from Journal state.
111#[derive(Clone, Debug, Default, PartialEq, Eq)]
112#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
113pub struct AccountLoad {
114    /// Is account and delegate code are loaded
115    pub load: Eip7702CodeLoad<()>,
116    /// Is account empty, if true account is not created.
117    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/// State load information that contains the data and if the account or storage is cold loaded.
135#[derive(Clone, Debug, Default, PartialEq, Eq)]
136#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
137pub struct StateLoad<T> {
138    /// returned data
139    pub data: T,
140    /// True if account is cold loaded.
141    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    /// Returns a new [`StateLoad`] with the given data and cold load status.
160    pub fn new(data: T, is_cold: bool) -> Self {
161        Self { data, is_cold }
162    }
163
164    /// Maps the data of the [`StateLoad`] to a new value.
165    ///
166    /// Useful for transforming the data of the [`StateLoad`] without changing the cold load status.
167    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/// EIP-7702 code load result that contains optional delegation is_cold information.
176///
177/// [`Self::is_delegate_account_cold`] will be [`Some`] if account has delegation.
178#[derive(Clone, Debug, Default, PartialEq, Eq)]
179#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
180pub struct Eip7702CodeLoad<T> {
181    /// returned data
182    pub state_load: StateLoad<T>,
183    /// True if account has delegate code and delegated account is cold loaded.
184    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    /// Returns a new [`Eip7702CodeLoad`] with the given data and without delegation.
203    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    /// Returns a new [`Eip7702CodeLoad`] with the given data and without delegation.
211    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    /// Deconstructs the [`Eip7702CodeLoad`] by extracting data and
219    /// returning a new [`Eip7702CodeLoad`] with empty data.
220    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    /// Sets the delegation cold load status.
232    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    /// Returns a new [`Eip7702CodeLoad`] with the given data and delegation cold load status.
237    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/// Result of a selfdestruct action.
246///
247/// Value returned are needed to calculate the gas spent.
248#[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}