revm/
context.rs

1mod context_precompiles;
2pub(crate) mod evm_context;
3mod inner_evm_context;
4
5pub use context_precompiles::{
6    ContextPrecompile, ContextPrecompiles, ContextStatefulPrecompile, ContextStatefulPrecompileArc,
7    ContextStatefulPrecompileBox, ContextStatefulPrecompileMut,
8};
9pub use evm_context::EvmContext;
10pub use inner_evm_context::InnerEvmContext;
11use revm_interpreter::{as_u64_saturated, Eip7702CodeLoad, StateLoad};
12
13use crate::{
14    db::{Database, EmptyDB},
15    interpreter::{AccountLoad, Host, SStoreResult, SelfDestructResult},
16    primitives::{Address, Bytes, Env, HandlerCfg, Log, B256, BLOCK_HASH_HISTORY, U256},
17};
18use std::boxed::Box;
19
20/// Main Context structure that contains both EvmContext and External context.
21pub struct Context<EXT, DB: Database> {
22    /// Evm Context (internal context).
23    pub evm: EvmContext<DB>,
24    /// External contexts.
25    pub external: EXT,
26}
27
28impl<EXT: Clone, DB: Database + Clone> Clone for Context<EXT, DB>
29where
30    DB::Error: Clone,
31{
32    fn clone(&self) -> Self {
33        Self {
34            evm: self.evm.clone(),
35            external: self.external.clone(),
36        }
37    }
38}
39
40impl Default for Context<(), EmptyDB> {
41    fn default() -> Self {
42        Self::new_empty()
43    }
44}
45
46impl Context<(), EmptyDB> {
47    /// Creates empty context. This is useful for testing.
48    pub fn new_empty() -> Context<(), EmptyDB> {
49        Context {
50            evm: EvmContext::new(EmptyDB::new()),
51            external: (),
52        }
53    }
54}
55
56impl<DB: Database> Context<(), DB> {
57    /// Creates new context with database.
58    pub fn new_with_db(db: DB) -> Context<(), DB> {
59        Context {
60            evm: EvmContext::new_with_env(db, Box::default()),
61            external: (),
62        }
63    }
64}
65
66impl<EXT, DB: Database> Context<EXT, DB> {
67    /// Creates new context with external and database.
68    pub fn new(evm: EvmContext<DB>, external: EXT) -> Context<EXT, DB> {
69        Context { evm, external }
70    }
71}
72
73/// Context with handler configuration.
74pub struct ContextWithHandlerCfg<EXT, DB: Database> {
75    /// Context of execution.
76    pub context: Context<EXT, DB>,
77    /// Handler configuration.
78    pub cfg: HandlerCfg,
79}
80
81impl<EXT, DB: Database> ContextWithHandlerCfg<EXT, DB> {
82    /// Creates new context with handler configuration.
83    pub fn new(context: Context<EXT, DB>, cfg: HandlerCfg) -> Self {
84        Self { cfg, context }
85    }
86}
87
88impl<EXT: Clone, DB: Database + Clone> Clone for ContextWithHandlerCfg<EXT, DB>
89where
90    DB::Error: Clone,
91{
92    fn clone(&self) -> Self {
93        Self {
94            context: self.context.clone(),
95            cfg: self.cfg,
96        }
97    }
98}
99
100impl<EXT, DB: Database> Host for Context<EXT, DB> {
101    /// Returns reference to Environment.
102    #[inline]
103    fn env(&self) -> &Env {
104        &self.evm.env
105    }
106
107    fn env_mut(&mut self) -> &mut Env {
108        &mut self.evm.env
109    }
110
111    fn block_hash(&mut self, requested_number: u64) -> Option<B256> {
112        let block_number = as_u64_saturated!(self.env().block.number);
113
114        let Some(diff) = block_number.checked_sub(requested_number) else {
115            return Some(B256::ZERO);
116        };
117
118        // blockhash should push zero if number is same as current block number.
119        if diff == 0 {
120            return Some(B256::ZERO);
121        }
122
123        if diff <= BLOCK_HASH_HISTORY {
124            return self
125                .evm
126                .block_hash(requested_number)
127                .map_err(|e| self.evm.error = Err(e))
128                .ok();
129        }
130
131        Some(B256::ZERO)
132    }
133
134    fn load_account_delegated(&mut self, address: Address) -> Option<AccountLoad> {
135        self.evm
136            .load_account_delegated(address)
137            .map_err(|e| self.evm.error = Err(e))
138            .ok()
139    }
140
141    fn balance(&mut self, address: Address) -> Option<StateLoad<U256>> {
142        self.evm
143            .balance(address)
144            .map_err(|e| self.evm.error = Err(e))
145            .ok()
146    }
147
148    fn code(&mut self, address: Address) -> Option<Eip7702CodeLoad<Bytes>> {
149        self.evm
150            .code(address)
151            .map_err(|e| self.evm.error = Err(e))
152            .ok()
153    }
154
155    fn code_hash(&mut self, address: Address) -> Option<Eip7702CodeLoad<B256>> {
156        self.evm
157            .code_hash(address)
158            .map_err(|e| self.evm.error = Err(e))
159            .ok()
160    }
161
162    fn sload(&mut self, address: Address, index: U256) -> Option<StateLoad<U256>> {
163        self.evm
164            .sload(address, index)
165            .map_err(|e| self.evm.error = Err(e))
166            .ok()
167    }
168
169    fn sstore(
170        &mut self,
171        address: Address,
172        index: U256,
173        value: U256,
174    ) -> Option<StateLoad<SStoreResult>> {
175        self.evm
176            .sstore(address, index, value)
177            .map_err(|e| self.evm.error = Err(e))
178            .ok()
179    }
180
181    fn tload(&mut self, address: Address, index: U256) -> U256 {
182        self.evm.tload(address, index)
183    }
184
185    fn tstore(&mut self, address: Address, index: U256, value: U256) {
186        self.evm.tstore(address, index, value)
187    }
188
189    fn log(&mut self, log: Log) {
190        self.evm.journaled_state.log(log);
191    }
192
193    fn selfdestruct(
194        &mut self,
195        address: Address,
196        target: Address,
197    ) -> Option<StateLoad<SelfDestructResult>> {
198        self.evm
199            .inner
200            .journaled_state
201            .selfdestruct(address, target, &mut self.evm.inner.db)
202            .map_err(|e| self.evm.error = Err(e))
203            .ok()
204    }
205}