foundry_evm/executors/
builder.rs1use crate::{
2 executors::Executor,
3 inspectors::{InspectorStackBuilder, TempoLabels},
4};
5use alloy_primitives::Address;
6use foundry_evm_core::{
7 backend::Backend,
8 evm::{
9 BlockEnvFor, EthEvmNetwork, EvmEnvFor, FoundryEvmNetwork, SpecFor, TempoEvmNetwork,
10 TxEnvFor,
11 },
12};
13use foundry_evm_networks::NetworkConfigs;
14use revm::context::{Block, Transaction};
15
16#[cfg(feature = "base")]
17use foundry_evm_core::evm::BaseEvmNetwork;
18
19#[cfg(feature = "monad")]
20use foundry_evm_core::{constants::MONAD_CHEATCODE_ADDRESS, evm::MonadEvmNetwork};
21
22#[cfg(feature = "optimism")]
23use foundry_evm_core::evm::OpEvmNetwork;
24
25#[derive(Debug, Clone)]
35#[must_use = "builders do nothing unless you call `build` on them"]
36pub struct ExecutorBuilder<FEN: FoundryEvmNetwork> {
37 stack: InspectorStackBuilder<BlockEnvFor<FEN>>,
39 gas_limit: Option<u64>,
41 spec: Option<SpecFor<FEN>>,
43 legacy_assertions: bool,
44}
45
46impl<FEN: FoundryEvmNetwork> Default for ExecutorBuilder<FEN> {
47 #[inline]
48 fn default() -> Self {
49 Self {
50 stack: InspectorStackBuilder::new().extra_cheatcode_addresses(&[]),
51 gas_limit: None,
52 spec: None,
53 legacy_assertions: false,
54 }
55 }
56}
57
58impl<FEN: FoundryEvmNetwork> ExecutorBuilder<FEN> {
59 #[inline]
61 pub const fn extra_cheatcode_addresses(&self) -> &'static [Address] {
62 self.stack.extra_cheatcode_addresses
63 }
64
65 #[inline]
67 pub fn inspectors(
68 mut self,
69 f: impl FnOnce(
70 InspectorStackBuilder<BlockEnvFor<FEN>>,
71 ) -> InspectorStackBuilder<BlockEnvFor<FEN>>,
72 ) -> Self {
73 self.stack = f(self.stack);
74 self
75 }
76
77 #[inline]
79 pub const fn spec_id(mut self, spec: SpecFor<FEN>) -> Self {
80 self.spec = Some(spec);
81 self
82 }
83
84 #[inline]
86 pub const fn spec_id_opt(self, spec: Option<SpecFor<FEN>>) -> Self {
87 if let Some(spec) = spec { self.spec_id(spec) } else { self }
88 }
89
90 #[inline]
92 pub const fn gas_limit(mut self, gas_limit: u64) -> Self {
93 self.gas_limit = Some(gas_limit);
94 self
95 }
96
97 #[inline]
99 pub const fn legacy_assertions(mut self, legacy_assertions: bool) -> Self {
100 self.legacy_assertions = legacy_assertions;
101 self
102 }
103
104 #[inline]
106 pub fn build(
107 self,
108 mut evm_env: EvmEnvFor<FEN>,
109 tx_env: TxEnvFor<FEN>,
110 db: Backend<FEN>,
111 networks: NetworkConfigs,
114 ) -> Executor<FEN> {
115 let Self { mut stack, gas_limit, spec, legacy_assertions, .. } = self;
116 stack.networks = networks;
117 if stack.block.is_none() {
118 stack.block = Some(evm_env.block_env.clone());
119 }
120 if stack.gas_price.is_none() {
121 stack.gas_price = Some(tx_env.gas_price());
122 }
123 let gas_limit = gas_limit.unwrap_or(evm_env.block_env.gas_limit());
124 if let Some(spec) = spec {
125 evm_env.cfg_env.set_spec_and_mainnet_gas_params(spec);
126 }
127 Executor::new(db, evm_env, tx_env, stack.build(), networks, gas_limit, legacy_assertions)
128 }
129}
130
131impl ExecutorBuilder<EthEvmNetwork> {
132 #[inline]
134 pub fn new() -> Self {
135 Self::default()
136 }
137}
138
139#[cfg(feature = "base")]
140impl ExecutorBuilder<BaseEvmNetwork> {
141 #[inline]
143 pub fn new() -> Self {
144 Self::default()
145 }
146}
147
148#[cfg(feature = "optimism")]
149impl ExecutorBuilder<OpEvmNetwork> {
150 #[inline]
152 pub fn new() -> Self {
153 Self::default()
154 }
155}
156
157impl ExecutorBuilder<TempoEvmNetwork> {
158 #[inline]
160 pub fn new() -> Self {
161 Self::default().inspectors(|stack| stack.tempo_labels(TempoLabels::default()))
162 }
163}
164
165#[cfg(feature = "monad")]
166impl ExecutorBuilder<MonadEvmNetwork> {
167 #[inline]
169 pub fn new() -> Self {
170 Self::default()
171 .inspectors(|stack| stack.extra_cheatcode_addresses(&[MONAD_CHEATCODE_ADDRESS]))
172 }
173}