revm_handler/
mainnet_builder.rs1use crate::{instructions::EthInstructions, EthPrecompiles};
2use context::{BlockEnv, Cfg, CfgEnv, Context, Evm, Journal, TxEnv};
3use context_interface::{Block, Database, JournalTr, Transaction};
4use database_interface::EmptyDB;
5use interpreter::interpreter::EthInterpreter;
6use primitives::hardfork::SpecId;
7
8pub type MainnetEvm<CTX, INSP = ()> =
9 Evm<CTX, INSP, EthInstructions<EthInterpreter, CTX>, EthPrecompiles>;
10
11pub type MainnetContext<DB> = Context<BlockEnv, TxEnv, CfgEnv, DB, Journal<DB>, ()>;
12
13pub trait MainBuilder: Sized {
14 type Context;
15
16 fn build_mainnet(self) -> MainnetEvm<Self::Context>;
17
18 fn build_mainnet_with_inspector<INSP>(self, inspector: INSP)
19 -> MainnetEvm<Self::Context, INSP>;
20}
21
22impl<BLOCK, TX, CFG, DB, JOURNAL, CHAIN> MainBuilder for Context<BLOCK, TX, CFG, DB, JOURNAL, CHAIN>
23where
24 BLOCK: Block,
25 TX: Transaction,
26 CFG: Cfg,
27 DB: Database,
28 JOURNAL: JournalTr<Database = DB>,
29{
30 type Context = Self;
31
32 fn build_mainnet(self) -> MainnetEvm<Self::Context> {
33 Evm {
34 ctx: self,
35 inspector: (),
36 instruction: EthInstructions::default(),
37 precompiles: EthPrecompiles::default(),
38 }
39 }
40
41 fn build_mainnet_with_inspector<INSP>(
42 self,
43 inspector: INSP,
44 ) -> MainnetEvm<Self::Context, INSP> {
45 Evm {
46 ctx: self,
47 inspector,
48 instruction: EthInstructions::default(),
49 precompiles: EthPrecompiles::default(),
50 }
51 }
52}
53
54pub trait MainContext {
56 fn mainnet() -> Self;
57}
58
59impl MainContext for Context<BlockEnv, TxEnv, CfgEnv, EmptyDB, Journal<EmptyDB>, ()> {
60 fn mainnet() -> Self {
61 Context::new(EmptyDB::new(), SpecId::default())
62 }
63}
64
65#[cfg(test)]
66mod test {
67 use crate::ExecuteEvm;
68 use crate::{MainBuilder, MainContext};
69 use alloy_signer::{Either, SignerSync};
70 use alloy_signer_local::PrivateKeySigner;
71 use bytecode::{
72 opcode::{PUSH1, SSTORE},
73 Bytecode,
74 };
75 use context::Context;
76 use context_interface::{transaction::Authorization, TransactionType};
77 use database::{BenchmarkDB, EEADDRESS, FFADDRESS};
78 use primitives::{hardfork::SpecId, TxKind, U256};
79
80 #[test]
81 fn sanity_eip7702_tx() {
82 let signer = PrivateKeySigner::random();
83 let auth = Authorization {
84 chain_id: U256::ZERO,
85 nonce: 0,
86 address: FFADDRESS,
87 };
88 let signature = signer.sign_hash_sync(&auth.signature_hash()).unwrap();
89 let auth = auth.into_signed(signature);
90
91 let bytecode = Bytecode::new_legacy([PUSH1, 0x01, PUSH1, 0x01, SSTORE].into());
92
93 let ctx = Context::mainnet()
94 .modify_cfg_chained(|cfg| cfg.spec = SpecId::PRAGUE)
95 .with_db(BenchmarkDB::new_bytecode(bytecode))
96 .modify_tx_chained(|tx| {
97 tx.tx_type = TransactionType::Eip7702.into();
98 tx.gas_limit = 100_000;
99 tx.authorization_list = vec![Either::Left(auth)];
100 tx.caller = EEADDRESS;
101 tx.kind = TxKind::Call(signer.address());
102 });
103
104 let mut evm = ctx.build_mainnet();
105
106 let ok = evm.replay().unwrap();
107
108 let auth_acc = ok.state.get(&signer.address()).unwrap();
109 assert_eq!(auth_acc.info.code, Some(Bytecode::new_eip7702(FFADDRESS)));
110 assert_eq!(auth_acc.info.nonce, 1);
111 assert_eq!(
112 auth_acc.storage.get(&U256::from(1)).unwrap().present_value,
113 U256::from(1)
114 );
115 }
116}