1use crate::{
2 execution, instructions::InstructionProvider, post_execution, pre_execution, validation, Frame,
3 FrameInitOrResult, FrameOrResult, FrameResult, ItemOrResult,
4};
5use auto_impl::auto_impl;
6use context::Evm;
7use context_interface::ContextTr;
8use context_interface::{
9 result::{HaltReasonTr, InvalidHeader, InvalidTransaction, ResultAndState},
10 Cfg, Database, Journal, Transaction,
11};
12use core::mem;
13use interpreter::{FrameInput, Host, InitialAndFloorGas, Interpreter, InterpreterAction};
14use precompile::PrecompileError;
15use primitives::Log;
16use state::EvmState;
17use std::{vec, vec::Vec};
18
19pub trait EvmTrError<EVM: EvmTr>:
20 From<InvalidTransaction>
21 + From<InvalidHeader>
22 + From<<<EVM::Context as ContextTr>::Db as Database>::Error>
23 + From<PrecompileError>
24{
25}
26
27impl<
28 EVM: EvmTr,
29 T: From<InvalidTransaction>
30 + From<InvalidHeader>
31 + From<<<EVM::Context as ContextTr>::Db as Database>::Error>
32 + From<PrecompileError>,
33 > EvmTrError<EVM> for T
34{
35}
36
37impl<CTX, INSP, I, P> EvmTr for Evm<CTX, INSP, I, P>
38where
39 CTX: ContextTr + Host,
40 I: InstructionProvider<Context = CTX, Output = InterpreterAction>,
41{
42 type Context = CTX;
43 type Instructions = I;
44 type Precompiles = P;
45
46 #[inline]
47 fn run_interpreter(
48 &mut self,
49 interpreter: &mut Interpreter<
50 <Self::Instructions as InstructionProvider>::InterpreterTypes,
51 >,
52 ) -> <Self::Instructions as InstructionProvider>::Output {
53 let context = &mut self.data.ctx;
54 let instructions = &mut self.instruction;
55 interpreter.run_plain(instructions.instruction_table(), context)
56 }
57 #[inline]
58 fn ctx(&mut self) -> &mut Self::Context {
59 &mut self.data.ctx
60 }
61
62 #[inline]
63 fn ctx_ref(&self) -> &Self::Context {
64 &self.data.ctx
65 }
66
67 #[inline]
68 fn ctx_instructions(&mut self) -> (&mut Self::Context, &mut Self::Instructions) {
69 (&mut self.data.ctx, &mut self.instruction)
70 }
71
72 #[inline]
73 fn ctx_precompiles(&mut self) -> (&mut Self::Context, &mut Self::Precompiles) {
74 (&mut self.data.ctx, &mut self.precompiles)
75 }
76}
77
78#[auto_impl(&mut, Box)]
79pub trait EvmTr {
80 type Context: ContextTr;
81 type Instructions: InstructionProvider;
82 type Precompiles;
83
84 fn run_interpreter(
85 &mut self,
86 interpreter: &mut Interpreter<
87 <Self::Instructions as InstructionProvider>::InterpreterTypes,
88 >,
89 ) -> <Self::Instructions as InstructionProvider>::Output;
90
91 fn ctx(&mut self) -> &mut Self::Context;
92
93 fn ctx_ref(&self) -> &Self::Context;
94
95 fn ctx_instructions(&mut self) -> (&mut Self::Context, &mut Self::Instructions);
96
97 fn ctx_precompiles(&mut self) -> (&mut Self::Context, &mut Self::Precompiles);
98}
99
100pub trait Handler {
101 type Evm: EvmTr<Context: ContextTr<Journal: Journal<FinalOutput = (EvmState, Vec<Log>)>>>;
102 type Error: EvmTrError<Self::Evm>;
103 type Frame: Frame<
106 Evm = Self::Evm,
107 Error = Self::Error,
108 FrameResult = FrameResult,
109 FrameInit = FrameInput,
110 >;
111 type HaltReason: HaltReasonTr;
113
114 #[inline]
115 fn run(
116 &mut self,
117 evm: &mut Self::Evm,
118 ) -> Result<ResultAndState<Self::HaltReason>, Self::Error> {
119 let init_and_floor_gas = self.validate(evm)?;
120 let eip7702_refund = self.pre_execution(evm)? as i64;
121 let exec_result = self.execution(evm, &init_and_floor_gas)?;
122 self.post_execution(evm, exec_result, init_and_floor_gas, eip7702_refund)
123 }
124 #[inline]
126 fn validate(&self, evm: &mut Self::Evm) -> Result<InitialAndFloorGas, Self::Error> {
127 self.validate_env(evm)?;
128 self.validate_tx_against_state(evm)?;
129 self.validate_initial_tx_gas(evm)
130 }
131
132 #[inline]
134 fn pre_execution(&self, evm: &mut Self::Evm) -> Result<u64, Self::Error> {
135 self.load_accounts(evm)?;
136 self.deduct_caller(evm)?;
137 let gas = self.apply_eip7702_auth_list(evm)?;
138 Ok(gas)
139 }
140
141 #[inline]
142 fn execution(
143 &mut self,
144 evm: &mut Self::Evm,
145 init_and_floor_gas: &InitialAndFloorGas,
146 ) -> Result<FrameResult, Self::Error> {
147 let gas_limit = evm.ctx().tx().gas_limit() - init_and_floor_gas.initial_gas;
148
149 let first_frame = self.create_first_frame(evm, gas_limit)?;
151 let mut frame_result = match first_frame {
152 ItemOrResult::Item(frame) => self.run_exec_loop(evm, frame)?,
153 ItemOrResult::Result(result) => result,
154 };
155
156 self.last_frame_result(evm, &mut frame_result)?;
157 Ok(frame_result)
158 }
159
160 #[inline]
161 fn post_execution(
162 &self,
163 evm: &mut Self::Evm,
164 mut exec_result: FrameResult,
165 init_and_floor_gas: InitialAndFloorGas,
166 eip7702_gas_refund: i64,
167 ) -> Result<ResultAndState<Self::HaltReason>, Self::Error> {
168 self.refund(evm, &mut exec_result, eip7702_gas_refund);
170 self.eip7623_check_gas_floor(evm, &mut exec_result, init_and_floor_gas);
172 self.reimburse_caller(evm, &mut exec_result)?;
174 self.reward_beneficiary(evm, &mut exec_result)?;
176 let output = self.output(evm, exec_result)?;
178 self.clear(evm);
180 Ok(output)
182 }
183
184 #[inline]
188 fn validate_env(&self, evm: &mut Self::Evm) -> Result<(), Self::Error> {
189 validation::validate_env(evm.ctx())
190 }
191
192 #[inline]
194 fn validate_tx_against_state(&self, evm: &mut Self::Evm) -> Result<(), Self::Error> {
195 validation::validate_tx_against_state(evm.ctx())
196 }
197
198 #[inline]
200 fn validate_initial_tx_gas(&self, evm: &Self::Evm) -> Result<InitialAndFloorGas, Self::Error> {
201 let ctx = evm.ctx_ref();
202 validation::validate_initial_tx_gas(ctx.tx(), ctx.cfg().spec().into()).map_err(From::from)
203 }
204
205 #[inline]
208 fn load_accounts(&self, evm: &mut Self::Evm) -> Result<(), Self::Error> {
209 pre_execution::load_accounts(evm.ctx())
210 }
211
212 #[inline]
213 fn apply_eip7702_auth_list(&self, evm: &mut Self::Evm) -> Result<u64, Self::Error> {
214 pre_execution::apply_eip7702_auth_list(evm.ctx())
215 }
216
217 #[inline]
218 fn deduct_caller(&self, evm: &mut Self::Evm) -> Result<(), Self::Error> {
219 pre_execution::deduct_caller(evm.ctx()).map_err(From::from)
220 }
221
222 #[inline]
224 fn create_first_frame(
225 &mut self,
226 evm: &mut Self::Evm,
227 gas_limit: u64,
228 ) -> Result<FrameOrResult<Self::Frame>, Self::Error> {
229 let ctx = evm.ctx_ref();
230 let init_frame = execution::create_init_frame(ctx.tx(), ctx.cfg().spec().into(), gas_limit);
231 self.frame_init_first(evm, init_frame)
232 }
233
234 #[inline]
235 fn last_frame_result(
236 &self,
237 evm: &mut Self::Evm,
238 frame_result: &mut <Self::Frame as Frame>::FrameResult,
239 ) -> Result<(), Self::Error> {
240 execution::last_frame_result(evm.ctx(), frame_result);
241 Ok(())
242 }
243
244 #[inline]
247 fn frame_init_first(
248 &mut self,
249 evm: &mut Self::Evm,
250 frame_input: <Self::Frame as Frame>::FrameInit,
251 ) -> Result<FrameOrResult<Self::Frame>, Self::Error> {
252 Self::Frame::init_first(evm, frame_input)
253 }
254
255 #[inline]
256 fn frame_init(
257 &mut self,
258 frame: &Self::Frame,
259 evm: &mut Self::Evm,
260 frame_input: <Self::Frame as Frame>::FrameInit,
261 ) -> Result<FrameOrResult<Self::Frame>, Self::Error> {
262 Frame::init(frame, evm, frame_input)
263 }
264
265 #[inline]
266 fn frame_call(
267 &mut self,
268 frame: &mut Self::Frame,
269 evm: &mut Self::Evm,
270 ) -> Result<FrameInitOrResult<Self::Frame>, Self::Error> {
271 Frame::run(frame, evm)
272 }
273
274 #[inline]
275 fn frame_return_result(
276 &mut self,
277 frame: &mut Self::Frame,
278 evm: &mut Self::Evm,
279 result: <Self::Frame as Frame>::FrameResult,
280 ) -> Result<(), Self::Error> {
281 Self::Frame::return_result(frame, evm, result)
282 }
283
284 #[inline]
285 fn run_exec_loop(
286 &mut self,
287 evm: &mut Self::Evm,
288 frame: Self::Frame,
289 ) -> Result<FrameResult, Self::Error> {
290 let mut frame_stack: Vec<Self::Frame> = vec![frame];
291 loop {
292 let frame = frame_stack.last_mut().unwrap();
293 let call_or_result = self.frame_call(frame, evm)?;
294
295 let result = match call_or_result {
296 ItemOrResult::Item(init) => {
297 match self.frame_init(frame, evm, init)? {
298 ItemOrResult::Item(new_frame) => {
299 frame_stack.push(new_frame);
300 continue;
301 }
302 ItemOrResult::Result(result) => result,
304 }
305 }
306 ItemOrResult::Result(result) => {
307 frame_stack.pop();
309 result
310 }
311 };
312
313 let Some(frame) = frame_stack.last_mut() else {
314 return Ok(result);
315 };
316 self.frame_return_result(frame, evm, result)?;
317 }
318 }
319
320 #[inline]
324 fn eip7623_check_gas_floor(
325 &self,
326 _evm: &mut Self::Evm,
327 exec_result: &mut <Self::Frame as Frame>::FrameResult,
328 init_and_floor_gas: InitialAndFloorGas,
329 ) {
330 post_execution::eip7623_check_gas_floor(exec_result.gas_mut(), init_and_floor_gas)
331 }
332
333 #[inline]
335 fn refund(
336 &self,
337 evm: &mut Self::Evm,
338 exec_result: &mut <Self::Frame as Frame>::FrameResult,
339 eip7702_refund: i64,
340 ) {
341 let spec = evm.ctx().cfg().spec().into();
342 post_execution::refund(spec, exec_result.gas_mut(), eip7702_refund)
343 }
344
345 #[inline]
347 fn reimburse_caller(
348 &self,
349 evm: &mut Self::Evm,
350 exec_result: &mut <Self::Frame as Frame>::FrameResult,
351 ) -> Result<(), Self::Error> {
352 post_execution::reimburse_caller(evm.ctx(), exec_result.gas_mut()).map_err(From::from)
353 }
354
355 #[inline]
357 fn reward_beneficiary(
358 &self,
359 evm: &mut Self::Evm,
360 exec_result: &mut <Self::Frame as Frame>::FrameResult,
361 ) -> Result<(), Self::Error> {
362 post_execution::reward_beneficiary(evm.ctx(), exec_result.gas_mut()).map_err(From::from)
363 }
364
365 #[inline]
367 fn output(
368 &self,
369 evm: &mut Self::Evm,
370 result: <Self::Frame as Frame>::FrameResult,
371 ) -> Result<ResultAndState<Self::HaltReason>, Self::Error> {
372 let ctx = evm.ctx();
373 mem::replace(ctx.error(), Ok(()))?;
374 Ok(post_execution::output(ctx, result))
375 }
376
377 #[inline]
383 fn end(
384 &self,
385 _evm: &mut Self::Evm,
386 end_output: Result<ResultAndState<Self::HaltReason>, Self::Error>,
387 ) -> Result<ResultAndState<Self::HaltReason>, Self::Error> {
388 end_output
389 }
390
391 #[inline]
395 fn clear(&self, evm: &mut Self::Evm) {
396 evm.ctx().journal().clear();
397 }
398}