revm_context_interface/
host.rs

1pub use crate::journaled_state::StateLoad;
2use database_interface::Database;
3
4use crate::{context::ContextTr, journaled_state::AccountLoad, Block, Journal};
5use primitives::{Address, Bytes, Log, B256, BLOCK_HASH_HISTORY, U256};
6
7/// EVM context host.
8pub trait Host: ContextTr {
9    fn set_error(&mut self, error: <Self::Db as Database>::Error) {
10        *self.error() = Err(error);
11    }
12
13    /// Gets the block hash of the given block `number`.
14    fn block_hash(&mut self, requested_number: u64) -> Option<B256> {
15        let block_number = self.block().number();
16
17        let Some(diff) = block_number.checked_sub(requested_number) else {
18            return Some(B256::ZERO);
19        };
20
21        // blockhash should push zero if number is same as current block number.
22        if diff == 0 {
23            return Some(B256::ZERO);
24        }
25
26        if diff <= BLOCK_HASH_HISTORY {
27            return self
28                .journal()
29                .db()
30                .block_hash(requested_number)
31                .map_err(|e| self.set_error(e))
32                .ok();
33        }
34
35        Some(B256::ZERO)
36    }
37
38    fn load_account_delegated(&mut self, address: Address) -> Option<StateLoad<AccountLoad>> {
39        self.journal()
40            .load_account_delegated(address)
41            .map_err(|e| self.set_error(e))
42            .ok()
43    }
44
45    /// Gets balance of `address` and if the account is cold.
46    fn balance(&mut self, address: Address) -> Option<StateLoad<U256>> {
47        self.journal()
48            .load_account(address)
49            .map(|acc| acc.map(|a| a.info.balance))
50            .map_err(|e| self.set_error(e))
51            .ok()
52    }
53
54    /// Gets code of `address` and if the account is cold.
55    fn code(&mut self, address: Address) -> Option<StateLoad<Bytes>> {
56        self.journal()
57            .code(address)
58            .map_err(|e| self.set_error(e))
59            .ok()
60    }
61
62    /// Gets code hash of `address` and if the account is cold.
63    fn code_hash(&mut self, address: Address) -> Option<StateLoad<B256>> {
64        self.journal()
65            .code_hash(address)
66            .map_err(|e| self.set_error(e))
67            .ok()
68    }
69
70    /// Gets storage value of `address` at `index` and if the account is cold.
71    fn sload(&mut self, address: Address, index: U256) -> Option<StateLoad<U256>> {
72        self.journal()
73            .sload(address, index)
74            .map_err(|e| self.set_error(e))
75            .ok()
76    }
77
78    /// Sets storage value of account address at index.
79    ///
80    /// Returns [`StateLoad`] with [`SStoreResult`] that contains original/new/old storage value.
81    fn sstore(
82        &mut self,
83        address: Address,
84        index: U256,
85        value: U256,
86    ) -> Option<StateLoad<SStoreResult>> {
87        self.journal()
88            .sstore(address, index, value)
89            .map_err(|e| self.set_error(e))
90            .ok()
91    }
92
93    /// Gets the transient storage value of `address` at `index`.
94    fn tload(&mut self, address: Address, index: U256) -> U256 {
95        self.journal().tload(address, index)
96    }
97
98    /// Sets the transient storage value of `address` at `index`.
99    fn tstore(&mut self, address: Address, index: U256, value: U256) {
100        self.journal().tstore(address, index, value)
101    }
102
103    /// Emits a log owned by `address` with given `LogData`.
104    fn log(&mut self, log: Log) {
105        self.journal().log(log);
106    }
107
108    /// Marks `address` to be deleted, with funds transferred to `target`.
109    fn selfdestruct(
110        &mut self,
111        address: Address,
112        target: Address,
113    ) -> Option<StateLoad<SelfDestructResult>> {
114        self.journal()
115            .selfdestruct(address, target)
116            .map_err(|e| self.set_error(e))
117            .ok()
118    }
119}
120
121impl<T: ContextTr> Host for T {}
122
123/// Represents the result of an `sstore` operation.
124#[derive(Clone, Debug, Default, PartialEq, Eq)]
125#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
126pub struct SStoreResult {
127    /// Value of the storage when it is first read
128    pub original_value: U256,
129    /// Current value of the storage
130    pub present_value: U256,
131    /// New value that is set
132    pub new_value: U256,
133}
134
135impl SStoreResult {
136    /// Returns `true` if the new value is equal to the present value.
137    #[inline]
138    pub fn is_new_eq_present(&self) -> bool {
139        self.new_value == self.present_value
140    }
141
142    /// Returns `true` if the original value is equal to the present value.
143    #[inline]
144    pub fn is_original_eq_present(&self) -> bool {
145        self.original_value == self.present_value
146    }
147
148    /// Returns `true` if the original value is equal to the new value.
149    #[inline]
150    pub fn is_original_eq_new(&self) -> bool {
151        self.original_value == self.new_value
152    }
153
154    /// Returns `true` if the original value is zero.
155    #[inline]
156    pub fn is_original_zero(&self) -> bool {
157        self.original_value.is_zero()
158    }
159
160    /// Returns `true` if the present value is zero.
161    #[inline]
162    pub fn is_present_zero(&self) -> bool {
163        self.present_value.is_zero()
164    }
165
166    /// Returns `true` if the new value is zero.
167    #[inline]
168    pub fn is_new_zero(&self) -> bool {
169        self.new_value.is_zero()
170    }
171}
172
173/// Result of a selfdestruct action
174///
175/// Value returned are needed to calculate the gas spent.
176#[derive(Clone, Debug, Default, PartialEq, Eq, Hash)]
177#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
178pub struct SelfDestructResult {
179    pub had_value: bool,
180    pub target_exists: bool,
181    pub previously_destroyed: bool,
182}