1use crate::{
2 db::{StateAcc, TryStateAcc},
3 helpers::{Ctx, Evm, Instruction},
4 inspectors::Layered,
5 ErroredState, EvmErrored, EvmExtUnchecked, Trevm,
6};
7use alloy::{
8 primitives::{Address, U256},
9 rpc::types::state::StateOverride,
10};
11use core::convert::Infallible;
12use revm::{
13 bytecode::opcode::DIFFICULTY,
14 context::{result::EVMError, Cfg as _, ContextTr},
15 handler::EthPrecompiles,
16 inspector::NoOpInspector,
17 interpreter::instructions::block_info,
18 primitives::hardfork::SpecId,
19 state::{AccountInfo, Bytecode, EvmState},
20 Database, DatabaseCommit, DatabaseRef, Inspector,
21};
22
23impl<Db, Insp, TrevmState> Trevm<Db, Insp, TrevmState>
24where
25 Db: Database,
26 Insp: Inspector<Ctx<Db>>,
27{
28 pub fn inner(&self) -> &Evm<Db, Insp> {
32 self.as_ref()
33 }
34
35 pub fn inner_mut_unchecked(&mut self) -> &mut Evm<Db, Insp> {
41 &mut self.inner
42 }
43
44 pub fn into_inner(self) -> Box<Evm<Db, Insp>> {
46 self.inner
47 }
48
49 pub fn into_db(self) -> Db {
51 self.inner.ctx.journaled_state.database
52 }
53
54 pub fn inspector(&self) -> &Insp {
56 &self.inner.inspector
57 }
58
59 pub fn inspector_mut(&mut self) -> &mut Insp {
61 &mut self.inner.inspector
62 }
63
64 pub fn replace_inspector(mut self, inspector: Insp) -> Self {
66 *self.inspector_mut() = inspector;
67 self
68 }
69
70 pub fn layer_inspector<Insp2>(
72 self,
73 inspector: Insp2,
74 ) -> Trevm<Db, Layered<Insp2, Insp>, TrevmState>
75 where
76 Insp2: Inspector<Ctx<Db>>,
77 {
78 let inner = Box::new(Evm {
79 ctx: self.inner.ctx,
80 inspector: Layered::new(inspector, self.inner.inspector),
81 instruction: self.inner.instruction,
82 precompiles: self.inner.precompiles,
83 frame_stack: self.inner.frame_stack,
84 });
85 Trevm { inner, state: self.state }
86 }
87
88 pub fn take_inspector(self) -> (Insp, Trevm<Db, NoOpInspector, TrevmState>) {
91 let inspector = self.inner.inspector;
92 let inner = Box::new(Evm {
93 ctx: self.inner.ctx,
94 inspector: NoOpInspector,
95 instruction: self.inner.instruction,
96 precompiles: self.inner.precompiles,
97 frame_stack: self.inner.frame_stack,
98 });
99 (inspector, Trevm { inner, state: self.state })
100 }
101
102 pub fn set_inspector<Insp2>(self, inspector: Insp2) -> Trevm<Db, Insp2, TrevmState>
104 where
105 Insp2: Inspector<Ctx<Db>>,
106 {
107 let inner = Box::new(Evm {
108 ctx: self.inner.ctx,
109 inspector,
110 instruction: self.inner.instruction,
111 precompiles: self.inner.precompiles,
112 frame_stack: self.inner.frame_stack,
113 });
114 Trevm { inner, state: self.state }
115 }
116
117 pub fn with_inspector<Insp2, F, NewState>(
120 self,
121 inspector: Insp2,
122 f: F,
123 ) -> Trevm<Db, Insp, NewState>
124 where
125 Insp2: Inspector<Ctx<Db>>,
126 F: FnOnce(Trevm<Db, Insp2, TrevmState>) -> Trevm<Db, Insp2, NewState>,
127 {
128 let (old, this) = self.take_inspector();
129 let this = f(this.set_inspector(inspector));
130 this.set_inspector(old)
131 }
132
133 pub fn try_with_inspector<F, Insp2, NewState, E>(
137 self,
138 inspector: Insp2,
139 f: F,
140 ) -> Result<Trevm<Db, Insp, NewState>, EvmErrored<Db, Insp, E>>
141 where
142 Insp2: Inspector<Ctx<Db>>,
143 F: FnOnce(
144 Trevm<Db, Insp2, TrevmState>,
145 ) -> Result<Trevm<Db, Insp2, NewState>, EvmErrored<Db, Insp2, E>>,
146 {
147 let (previous, this) = self.take_inspector();
148 let this = this.set_inspector(inspector);
149
150 match f(this) {
151 Ok(evm) => Ok(evm.set_inspector(previous)),
152 Err(evm) => Err(evm.set_inspector(previous)),
153 }
154 }
155
156 pub fn spec_id(&self) -> SpecId {
158 self.inner.ctx.cfg().spec()
159 }
160
161 pub fn set_spec_id(&mut self, spec_id: SpecId) {
165 self.inner.modify_cfg(|cfg| cfg.spec = spec_id);
166 }
167
168 pub fn with_spec_id<F, NewState>(mut self, spec_id: SpecId, f: F) -> Trevm<Db, Insp, NewState>
171 where
172 F: FnOnce(Self) -> Trevm<Db, Insp, NewState>,
173 {
174 let old = self.spec_id();
175 self.set_spec_id(spec_id);
176 let mut this = f(self);
177 this.set_spec_id(old);
178 this
179 }
180
181 pub fn errored<E>(self, error: E) -> EvmErrored<Db, Insp, E> {
183 EvmErrored { inner: self.inner, state: ErroredState { error } }
184 }
185
186 pub fn apply_state_overrides(
189 mut self,
190 overrides: &StateOverride,
191 ) -> Result<Self, EVMError<<Db as Database>::Error>>
192 where
193 Db: DatabaseCommit,
194 {
195 for (address, account_override) in overrides {
196 if let Some(balance) = account_override.balance {
197 self.inner.set_balance(*address, balance).map_err(EVMError::Database)?;
198 }
199 if let Some(nonce) = account_override.nonce {
200 self.inner.set_nonce(*address, nonce).map_err(EVMError::Database)?;
201 }
202 if let Some(code) = account_override.code.as_ref() {
203 self.inner
204 .set_bytecode(
205 *address,
206 Bytecode::new_raw_checked(code.clone())
207 .map_err(|_| EVMError::Custom("Invalid bytecode".to_string()))?,
208 )
209 .map_err(EVMError::Database)?;
210 }
211 if let Some(state) = account_override.state.as_ref() {
212 for (slot, value) in state {
213 self.inner
214 .set_storage(
215 *address,
216 U256::from_be_bytes((*slot).into()),
217 U256::from_be_bytes((*value).into()),
218 )
219 .map_err(EVMError::Database)?;
220 }
221 }
222 }
223 Ok(self)
224 }
225
226 pub fn maybe_apply_state_overrides(
228 self,
229 overrides: Option<&StateOverride>,
230 ) -> Result<Self, EVMError<<Db as Database>::Error>>
231 where
232 Db: DatabaseCommit,
233 {
234 if let Some(overrides) = overrides {
235 self.apply_state_overrides(overrides)
236 } else {
237 Ok(self)
238 }
239 }
240
241 pub fn override_opcode(&mut self, opcode: u8, handler: Instruction<Db>) -> Instruction<Db> {
244 std::mem::replace(&mut self.inner.instruction.instruction_table[opcode as usize], handler)
245 }
246
247 pub fn disable_opcode(&mut self, opcode: u8) -> Instruction<Db> {
250 self.override_opcode(opcode, Instruction::new(crate::helpers::forbidden, 0))
251 }
252
253 pub fn with_opcode_override<F, NewState>(
256 mut self,
257 opcode: u8,
258 handler: Instruction<Db>,
259 f: F,
260 ) -> Trevm<Db, Insp, NewState>
261 where
262 F: FnOnce(Self) -> Trevm<Db, Insp, NewState>,
263 {
264 let old = self.override_opcode(opcode, handler);
265 self.inner.instruction.insert_instruction(opcode, handler);
266 let mut this = f(self);
267 this.override_opcode(opcode, old);
268 this
269 }
270
271 pub fn disable_prevrandao(&mut self) -> Instruction<Db> {
275 self.disable_opcode(DIFFICULTY)
276 }
277
278 pub fn enable_prevrandao(&mut self) -> Instruction<Db> {
281 self.override_opcode(DIFFICULTY, Instruction::new(block_info::difficulty, 2))
282 }
283
284 pub fn without_prevrandao<F, NewState>(self, f: F) -> Trevm<Db, Insp, NewState>
288 where
289 F: FnOnce(Self) -> Trevm<Db, Insp, NewState>,
290 {
291 self.with_opcode_override(DIFFICULTY, Instruction::new(crate::helpers::forbidden, 0), f)
292 }
293
294 pub fn override_precompiles(&mut self, precompiles: EthPrecompiles) -> EthPrecompiles {
297 std::mem::replace(&mut self.inner.precompiles, precompiles)
298 }
299
300 pub fn with_precompiles<F, NewState>(
303 mut self,
304 precompiles: EthPrecompiles,
305 f: F,
306 ) -> Trevm<Db, Insp, NewState>
307 where
308 F: FnOnce(Self) -> Trevm<Db, Insp, NewState>,
309 {
310 let old = self.override_precompiles(precompiles);
311 let mut this = f(self);
312 this.override_precompiles(old);
313 this
314 }
315}
316
317impl<Db, Insp, TrevmState> Trevm<Db, Insp, TrevmState>
319where
320 Db: Database,
321 Insp: Inspector<Ctx<Db>>,
322{
323 pub fn try_read_account(
327 &mut self,
328 address: Address,
329 ) -> Result<Option<AccountInfo>, <Db as Database>::Error> {
330 self.inner.db_mut().basic(address)
331 }
332
333 pub fn try_read_nonce(&mut self, address: Address) -> Result<u64, <Db as Database>::Error> {
337 self.try_read_account(address).map(|a| a.map(|a| a.nonce).unwrap_or_default())
338 }
339
340 pub fn try_read_balance(&mut self, address: Address) -> Result<U256, <Db as Database>::Error> {
344 self.try_read_account(address).map(|a| a.map(|a| a.balance).unwrap_or_default())
345 }
346
347 pub fn try_read_storage(
351 &mut self,
352 address: Address,
353 slot: U256,
354 ) -> Result<U256, <Db as Database>::Error> {
355 self.inner.db_mut().storage(address, slot)
356 }
357
358 pub fn try_read_code(
362 &mut self,
363 address: Address,
364 ) -> Result<Option<Bytecode>, <Db as Database>::Error> {
365 let acct_info = self.try_read_account(address)?;
366 match acct_info {
367 Some(acct) => Ok(Some(self.inner.db_mut().code_by_hash(acct.code_hash)?)),
368 None => Ok(None),
369 }
370 }
371
372 pub fn try_gas_allowance(
374 &mut self,
375 caller: Address,
376 gas_price: u128,
377 ) -> Result<u64, <Db as Database>::Error> {
378 if gas_price == 0 {
379 return Ok(u64::MAX);
380 }
381 let gas_price = U256::from(gas_price);
382 let balance = self.try_read_balance(caller)?;
383 Ok((balance / gas_price).saturating_to())
384 }
385}
386
387impl<Db, Insp, TrevmState> Trevm<Db, Insp, TrevmState>
389where
390 Db: Database + DatabaseRef,
391 Insp: Inspector<Ctx<Db>>,
392{
393 pub fn try_read_account_ref(
395 &self,
396 address: Address,
397 ) -> Result<Option<AccountInfo>, <Db as DatabaseRef>::Error> {
398 self.inner.db_ref().basic_ref(address)
399 }
400
401 pub fn try_read_nonce_ref(&self, address: Address) -> Result<u64, <Db as DatabaseRef>::Error> {
405 self.try_read_account_ref(address).map(|a| a.map(|a| a.nonce).unwrap_or_default())
406 }
407
408 pub fn try_read_balance_ref(
412 &self,
413 address: Address,
414 ) -> Result<U256, <Db as DatabaseRef>::Error> {
415 self.try_read_account_ref(address).map(|a| a.map(|a| a.balance).unwrap_or_default())
416 }
417
418 pub fn try_read_storage_ref(
420 &self,
421 address: Address,
422 slot: U256,
423 ) -> Result<U256, <Db as DatabaseRef>::Error> {
424 self.inner.db_ref().storage_ref(address, slot)
425 }
426
427 pub fn try_read_code_ref(
429 &self,
430 address: Address,
431 ) -> Result<Option<Bytecode>, <Db as DatabaseRef>::Error> {
432 let acct_info = self.try_read_account_ref(address)?;
433 match acct_info {
434 Some(acct) => Ok(Some(self.inner.db_ref().code_by_hash_ref(acct.code_hash)?)),
435 None => Ok(None),
436 }
437 }
438
439 pub fn try_gas_allowance_ref(
441 &self,
442 caller: Address,
443 gas_price: U256,
444 ) -> Result<u64, <Db as DatabaseRef>::Error> {
445 if gas_price.is_zero() {
446 return Ok(u64::MAX);
447 }
448 let gas_price = U256::from(gas_price);
449 let balance = self.try_read_balance_ref(caller)?;
450 Ok((balance / gas_price).saturating_to())
451 }
452}
453
454impl<Db, Insp, TrevmState> Trevm<Db, Insp, TrevmState>
456where
457 Db: Database<Error = Infallible>,
458 Insp: Inspector<Ctx<Db>>,
459{
460 pub fn read_account(&mut self, address: Address) -> Option<AccountInfo> {
464 self.inner.db_mut().basic(address).expect("infallible")
465 }
466
467 pub fn read_nonce(&mut self, address: Address) -> u64 {
471 self.read_account(address).map(|a: AccountInfo| a.nonce).unwrap_or_default()
472 }
473
474 pub fn read_balance(&mut self, address: Address) -> U256 {
478 self.read_account(address).map(|a: AccountInfo| a.balance).unwrap_or_default()
479 }
480
481 pub fn read_storage(&mut self, address: Address, slot: U256) -> U256 {
485 self.inner.db_mut().storage(address, slot).expect("infallible")
486 }
487
488 pub fn read_code(&mut self, address: Address) -> Option<Bytecode> {
492 let acct_info = self.read_account(address)?;
493 Some(self.inner.db_mut().code_by_hash(acct_info.code_hash).expect("infallible"))
494 }
495}
496
497impl<Db, Insp, TrevmState> Trevm<Db, Insp, TrevmState>
499where
500 Db: Database + DatabaseRef,
501 Insp: Inspector<Ctx<Db>>,
502{
503 pub fn read_account_ref(&self, address: Address) -> Option<AccountInfo> {
507 self.inner.db_ref().basic_ref(address).expect("infallible")
508 }
509
510 pub fn read_nonce_ref(&self, address: Address) -> u64 {
512 self.read_account_ref(address).map(|a: AccountInfo| a.nonce).unwrap_or_default()
513 }
514
515 pub fn read_balance_ref(&self, address: Address) -> U256 {
517 self.read_account_ref(address).map(|a: AccountInfo| a.balance).unwrap_or_default()
518 }
519
520 pub fn read_storage_ref(&self, address: Address, slot: U256) -> U256 {
524 self.inner.db_ref().storage_ref(address, slot).expect("infallible")
525 }
526
527 pub fn read_code_ref(&self, address: Address) -> Option<Bytecode> {
531 let acct_info = self.read_account_ref(address)?;
532 Some(self.inner.db_ref().code_by_hash_ref(acct_info.code_hash).expect("infallible"))
533 }
534}
535
536impl<Db, Insp, TrevmState> Trevm<Db, Insp, TrevmState>
537where
538 Db: Database,
539 Insp: Inspector<Ctx<Db>>,
540{
541 pub fn commit_unchecked(&mut self, state: EvmState)
545 where
546 Db: DatabaseCommit,
547 {
548 self.inner.db_mut().commit(state);
549 }
550
551 pub fn try_modify_account_unchecked<F: FnOnce(&mut AccountInfo)>(
554 &mut self,
555 address: Address,
556 f: F,
557 ) -> Result<AccountInfo, <Db as Database>::Error>
558 where
559 Db: DatabaseCommit,
560 {
561 self.inner.modify_account(address, f)
562 }
563
564 pub fn try_set_nonce_unchecked(
567 &mut self,
568 address: Address,
569 nonce: u64,
570 ) -> Result<u64, <Db as Database>::Error>
571 where
572 Db: DatabaseCommit,
573 {
574 self.inner.set_nonce(address, nonce)
575 }
576
577 pub fn try_increment_nonce_unchecked(
583 &mut self,
584 address: Address,
585 ) -> Result<u64, <Db as Database>::Error>
586 where
587 Db: DatabaseCommit,
588 {
589 self.inner.increment_nonce(address)
590 }
591
592 pub fn try_decrement_nonce_unchecked(
597 &mut self,
598 address: Address,
599 ) -> Result<u64, <Db as Database>::Error>
600 where
601 Db: DatabaseCommit,
602 {
603 self.inner.decrement_nonce(address)
604 }
605
606 pub fn try_set_storage_unchecked(
609 &mut self,
610 address: Address,
611 slot: U256,
612 value: U256,
613 ) -> Result<U256, <Db as Database>::Error>
614 where
615 Db: DatabaseCommit,
616 {
617 self.inner.set_storage(address, slot, value)
618 }
619
620 pub fn try_set_bytecode_unchecked(
624 &mut self,
625 address: Address,
626 bytecode: Bytecode,
627 ) -> Result<Option<Bytecode>, <Db as Database>::Error>
628 where
629 Db: DatabaseCommit,
630 {
631 self.inner.set_bytecode(address, bytecode)
632 }
633
634 pub fn try_increase_balance_unchecked(
640 &mut self,
641 address: Address,
642 amount: U256,
643 ) -> Result<U256, <Db as Database>::Error>
644 where
645 Db: DatabaseCommit,
646 {
647 self.inner.increase_balance(address, amount)
648 }
649
650 pub fn try_decrease_balance_unchecked(
655 &mut self,
656 address: Address,
657 amount: U256,
658 ) -> Result<U256, <Db as Database>::Error>
659 where
660 Db: DatabaseCommit,
661 {
662 self.inner.decrease_balance(address, amount)
663 }
664
665 pub fn try_set_balance_unchecked(
668 &mut self,
669 address: Address,
670 amount: U256,
671 ) -> Result<U256, <Db as Database>::Error>
672 where
673 Db: DatabaseCommit,
674 {
675 self.inner.set_balance(address, amount)
676 }
677}
678
679impl<Db, Insp, TrevmState> Trevm<Db, Insp, TrevmState>
680where
681 Db: Database<Error = Infallible>,
682 Insp: Inspector<Ctx<Db>>,
683{
684 pub fn modify_account_unchecked(
687 &mut self,
688 address: Address,
689 f: impl FnOnce(&mut AccountInfo),
690 ) -> AccountInfo
691 where
692 Db: DatabaseCommit,
693 {
694 self.try_modify_account_unchecked(address, f).expect("infallible")
695 }
696
697 pub fn set_nonce_unchecked(&mut self, address: Address, nonce: u64) -> u64
700 where
701 Db: DatabaseCommit,
702 {
703 self.try_set_nonce_unchecked(address, nonce).expect("infallible")
704 }
705
706 pub fn increment_nonce_unchecked(&mut self, address: Address) -> u64
712 where
713 Db: DatabaseCommit,
714 {
715 self.try_increment_nonce_unchecked(address).expect("infallible")
716 }
717
718 pub fn decrement_nonce_unchecked(&mut self, address: Address) -> u64
723 where
724 Db: DatabaseCommit,
725 {
726 self.try_decrement_nonce_unchecked(address).expect("infallible")
727 }
728
729 pub fn set_storage_unchecked(&mut self, address: Address, slot: U256, value: U256) -> U256
732 where
733 Db: DatabaseCommit,
734 {
735 self.try_set_storage_unchecked(address, slot, value).expect("infallible")
736 }
737
738 pub fn set_bytecode_unchecked(
742 &mut self,
743 address: Address,
744 bytecode: Bytecode,
745 ) -> Option<Bytecode>
746 where
747 Db: DatabaseCommit,
748 {
749 self.try_set_bytecode_unchecked(address, bytecode).expect("infallible")
750 }
751
752 pub fn increase_balance_unchecked(&mut self, address: Address, amount: U256) -> U256
755 where
756 Db: DatabaseCommit,
757 {
758 self.try_increase_balance_unchecked(address, amount).expect("infallible")
759 }
760
761 pub fn decrease_balance_unchecked(&mut self, address: Address, amount: U256) -> U256
764 where
765 Db: DatabaseCommit,
766 {
767 self.try_decrease_balance_unchecked(address, amount).expect("infallible")
768 }
769
770 pub fn set_balance_unchecked(&mut self, address: Address, amount: U256) -> U256
773 where
774 Db: DatabaseCommit,
775 {
776 self.try_set_balance_unchecked(address, amount).expect("infallible")
777 }
778}
779
780impl<Db, Outer, Inner, TrevmState> Trevm<Db, Layered<Outer, Inner>, TrevmState>
782where
783 Db: Database,
784 Outer: Inspector<Ctx<Db>>,
785 Inner: Inspector<Ctx<Db>>,
786{
787 pub fn take_outer(self) -> (Outer, Trevm<Db, Inner, TrevmState>) {
790 let (outer, inner) = self.inner.inspector.into_parts();
791
792 (
793 outer,
794 Trevm {
795 inner: Box::new(Evm {
796 ctx: self.inner.ctx,
797 inspector: inner,
798 instruction: self.inner.instruction,
799 precompiles: self.inner.precompiles,
800 frame_stack: self.inner.frame_stack,
801 }),
802 state: self.state,
803 },
804 )
805 }
806
807 pub fn remove_outer(self) -> Trevm<Db, Inner, TrevmState> {
810 self.take_outer().1
811 }
812
813 pub fn take_inner(self) -> (Inner, Trevm<Db, Outer, TrevmState>) {
816 let (outer, inner) = self.inner.inspector.into_parts();
817
818 (
819 inner,
820 Trevm {
821 inner: Box::new(Evm {
822 ctx: self.inner.ctx,
823 inspector: outer,
824 instruction: self.inner.instruction,
825 precompiles: self.inner.precompiles,
826 frame_stack: self.inner.frame_stack,
827 }),
828 state: self.state,
829 },
830 )
831 }
832
833 pub fn remove_inner(self) -> Trevm<Db, Outer, TrevmState> {
836 self.take_inner().1
837 }
838}
839
840impl<Db, Insp, TrevmState> Trevm<Db, Insp, TrevmState>
843where
844 Db: Database + StateAcc,
845 Insp: Inspector<Ctx<Db>>,
846{
847 pub fn set_state_clear_flag(&mut self, flag: bool) {
850 self.inner.db_mut().set_state_clear_flag(flag)
851 }
852}
853
854impl<Db, Insp, TrevmState> Trevm<Db, Insp, TrevmState>
855where
856 Db: Database + TryStateAcc,
857 Insp: Inspector<Ctx<Db>>,
858{
859 pub fn try_set_state_clear_flag(
865 &mut self,
866 flag: bool,
867 ) -> Result<(), <Db as TryStateAcc>::Error> {
868 self.inner.db_mut().try_set_state_clear_flag(flag)
869 }
870}
871
872