1use alloc::boxed::Box;
4use revm::{inspector_handle_register, Database, Evm, EvmBuilder, GetInspector};
5use revm_primitives::EnvWithHandlerCfg;
6
7#[derive(Debug)]
14pub struct RethEvmBuilder<DB: Database, EXT = ()> {
15 db: DB,
17 env: Option<Box<EnvWithHandlerCfg>>,
19 external_context: EXT,
21}
22
23impl<DB, EXT> RethEvmBuilder<DB, EXT>
24where
25 DB: Database,
26{
27 pub const fn new(db: DB, external_context: EXT) -> Self {
29 Self { db, env: None, external_context }
30 }
31
32 pub fn with_env(mut self, env: Box<EnvWithHandlerCfg>) -> Self {
34 self.env = Some(env);
35 self
36 }
37
38 pub fn with_external_context<EXT1>(self, external_context: EXT1) -> RethEvmBuilder<DB, EXT1> {
40 RethEvmBuilder { db: self.db, env: self.env, external_context }
41 }
42
43 pub fn build<'a>(self) -> Evm<'a, EXT, DB> {
45 let mut builder =
46 EvmBuilder::default().with_db(self.db).with_external_context(self.external_context);
47
48 if let Some(env) = self.env {
50 builder = builder.with_spec_id(env.spec_id());
51 builder = builder.with_env(env.env);
52 }
53
54 builder.build()
55 }
56
57 pub fn build_with_inspector<'a, I>(self, inspector: I) -> Evm<'a, I, DB>
59 where
60 I: GetInspector<DB>,
61 EXT: 'a,
62 {
63 let mut builder =
64 EvmBuilder::default().with_db(self.db).with_external_context(self.external_context);
65 if let Some(env) = self.env {
66 builder = builder.with_spec_id(env.spec_id());
67 builder = builder.with_env(env.env);
68 }
69 builder
70 .with_external_context(inspector)
71 .append_handler_register(inspector_handle_register)
72 .build()
73 }
74}
75
76pub trait ConfigureEvmBuilder {
78 type Builder<'a, DB: Database>: EvmFactory;
80}
81
82pub trait EvmFactory {
84 type DefaultExternalContext<'a>;
86
87 fn default_external_context<'a>(&self) -> Self::DefaultExternalContext<'a>;
89
90 fn evm<DB: Database>(self, db: DB) -> Evm<'static, Self::DefaultExternalContext<'static>, DB>
96 where
97 Self: Sized,
98 {
99 RethEvmBuilder::new(db, self.default_external_context()).build()
100 }
101
102 fn evm_with_env<'a, DB: Database + 'a>(
107 &self,
108 db: DB,
109 env: EnvWithHandlerCfg,
110 ) -> Evm<'a, Self::DefaultExternalContext<'a>, DB> {
111 RethEvmBuilder::new(db, self.default_external_context()).with_env(env.into()).build()
112 }
113
114 fn evm_with_env_and_inspector<DB, I>(
121 &self,
122 db: DB,
123 env: EnvWithHandlerCfg,
124 inspector: I,
125 ) -> Evm<'_, I, DB>
126 where
127 DB: Database,
128 I: GetInspector<DB>,
129 {
130 RethEvmBuilder::new(db, self.default_external_context())
131 .with_env(env.into())
132 .build_with_inspector(inspector)
133 }
134
135 fn evm_with_inspector<DB, I>(&self, db: DB, inspector: I) -> Evm<'_, I, DB>
141 where
142 DB: Database,
143 I: GetInspector<DB>,
144 {
145 RethEvmBuilder::new(db, self.default_external_context()).build_with_inspector(inspector)
146 }
147}
148
149impl<DB: Database, EXT: Clone> EvmFactory for RethEvmBuilder<DB, EXT> {
150 type DefaultExternalContext<'a> = EXT;
151
152 fn default_external_context<'a>(&self) -> Self::DefaultExternalContext<'a> {
153 self.external_context.clone()
154 }
155}