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
20pub struct Context<EXT, DB: Database> {
22 pub evm: EvmContext<DB>,
24 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 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 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 pub fn new(evm: EvmContext<DB>, external: EXT) -> Context<EXT, DB> {
69 Context { evm, external }
70 }
71}
72
73pub struct ContextWithHandlerCfg<EXT, DB: Database> {
75 pub context: Context<EXT, DB>,
77 pub cfg: HandlerCfg,
79}
80
81impl<EXT, DB: Database> ContextWithHandlerCfg<EXT, DB> {
82 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 #[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 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}