foundry_cheatcodes/
lib.rs1#![cfg_attr(not(test), warn(unused_crate_dependencies))]
6#![cfg_attr(docsrs, feature(doc_cfg))]
7#![allow(elided_lifetimes_in_paths)] #[macro_use]
10extern crate foundry_common;
11
12#[macro_use]
13pub extern crate foundry_cheatcodes_spec as spec;
14
15#[macro_use]
16extern crate tracing;
17
18use alloy_primitives::{Address, B256, U256};
19use foundry_evm_core::{
20 FoundryTransaction,
21 backend::{DatabaseExt, LocalForkId},
22 env::FoundryContextExt,
23 evm::{FoundryContextFor, FoundryEvmNetwork, SpecFor},
24 fork::CreateFork,
25};
26use revm::context::{Block, Cfg, ContextTr, JournalTr, Transaction};
27
28pub use Vm::ForgeContext;
29pub use config::CheatsConfig;
30pub use error::{Error, ErrorKind, Result};
31pub use foundry_evm_core::evm::NestedEvmClosureFor;
32pub use inspector::{
33 BroadcastableTransaction, BroadcastableTransactions, Cheatcodes, CheatcodesExecutor,
34};
35pub use spec::{CheatcodeDef, Vm};
36
37#[macro_use]
38mod error;
39
40mod base64;
41
42mod config;
43
44mod crypto;
45
46mod version;
47
48mod env;
49pub use env::{current_execution_context, set_execution_context};
50
51mod evm;
52
53mod expected_emit;
54
55mod external_storage;
56
57mod fs;
58
59mod inspector;
60pub use inspector::CheatcodeAnalysis;
61
62mod json;
63
64#[cfg(feature = "monad")]
65mod monad;
66
67mod script;
68pub use script::{Wallets, WalletsInner};
69
70mod string;
71
72mod tempo;
73
74mod test;
75pub use test::expect::ExpectedCallTracker;
76
77mod toml;
78
79mod utils;
80
81pub(crate) trait Cheatcode: CheatcodeDef {
83 fn apply<FEN: FoundryEvmNetwork>(&self, state: &mut Cheatcodes<FEN>) -> Result {
87 let _ = state;
88 unimplemented!("{}", Self::CHEATCODE.func.id)
89 }
90
91 #[inline(always)]
95 fn apply_stateful<FEN: FoundryEvmNetwork>(&self, ccx: &mut CheatsCtxt<'_, '_, FEN>) -> Result {
96 self.apply(ccx.state)
97 }
98
99 #[inline(always)]
103 fn apply_full<FEN: FoundryEvmNetwork>(
104 &self,
105 ccx: &mut CheatsCtxt<'_, '_, FEN>,
106 executor: &mut dyn CheatcodesExecutor<FEN>,
107 ) -> Result {
108 let _ = executor;
109 self.apply_stateful(ccx)
110 }
111}
112
113pub struct CheatsCtxt<'a, 'db, FEN: FoundryEvmNetwork + 'db> {
115 pub(crate) state: &'a mut Cheatcodes<FEN>,
117 pub(crate) ecx: &'a mut FoundryContextFor<'db, FEN>,
119 pub(crate) caller: Address,
121 pub(crate) gas_limit: u64,
123 pub(crate) is_static: bool,
125}
126
127impl<FEN: FoundryEvmNetwork> CheatsCtxt<'_, '_, FEN> {
128 pub(crate) fn ensure_not_precompile(&self, address: &Address) -> Result<()> {
129 if self.is_precompile(address) { Err(precompile_error(address)) } else { Ok(()) }
130 }
131
132 pub(crate) fn is_precompile(&self, address: &Address) -> bool {
133 self.ecx.journal().precompile_addresses().contains(address)
134 }
135
136 #[inline]
138 pub(crate) fn depth(&self) -> usize {
139 self.ecx.journal().depth()
140 }
141
142 #[inline]
144 pub(crate) fn spec(&self) -> SpecFor<FEN> {
145 self.ecx.cfg().spec()
146 }
147
148 #[inline]
150 pub(crate) fn chain_id(&self) -> u64 {
151 self.ecx.cfg().chain_id()
152 }
153
154 #[inline]
156 pub(crate) fn max_initcode_size(&self) -> usize {
157 self.ecx.cfg().max_initcode_size()
158 }
159
160 #[inline]
162 pub(crate) fn limit_contract_code_size(&self) -> Option<usize> {
163 self.ecx.cfg_env().limit_contract_code_size
164 }
165
166 #[inline]
168 pub(crate) fn block_number(&self) -> U256 {
169 self.ecx.block().number()
170 }
171
172 #[inline]
174 pub(crate) fn timestamp(&self) -> U256 {
175 self.ecx.block().timestamp()
176 }
177
178 #[inline]
180 pub(crate) fn basefee(&self) -> u64 {
181 self.ecx.block().basefee()
182 }
183
184 #[inline]
186 pub(crate) fn slot_num(&self) -> u64 {
187 self.ecx.block().slot_num()
188 }
189
190 #[inline]
192 pub(crate) fn blob_excess_gas(&self) -> Option<u64> {
193 self.ecx.block().blob_excess_gas()
194 }
195
196 #[inline]
198 pub(crate) fn tx_caller(&self) -> Address {
199 self.ecx.tx().caller()
200 }
201
202 #[inline]
204 pub(crate) fn tx_gas_price(&self) -> u128 {
205 self.ecx.tx().gas_price()
206 }
207
208 #[inline]
210 pub(crate) fn tx_type(&self) -> u8 {
211 self.ecx.tx().tx_type()
212 }
213
214 #[inline]
216 pub(crate) fn tx_blob_hashes(&self) -> &[B256] {
217 self.ecx.tx().blob_versioned_hashes()
218 }
219
220 #[inline]
222 pub(crate) fn tx_fee_token(&self) -> Option<Address> {
223 self.ecx.tx().fee_token()
224 }
225
226 #[inline]
228 pub(crate) fn active_fork_id(&self) -> Option<LocalForkId> {
229 self.ecx.db().active_fork_id()
230 }
231
232 #[inline]
234 pub(crate) fn active_fork_url(&self) -> Option<String> {
235 self.ecx.db().active_fork_url()
236 }
237
238 #[inline]
240 pub(crate) fn active_fork_block_number(&self) -> Option<u64> {
241 self.ecx.db().active_fork_block_number()
242 }
243
244 #[inline]
246 pub(crate) fn active_fork_options(&self) -> Option<CreateFork> {
247 self.ecx.db().active_fork_options()
248 }
249
250 #[inline]
252 pub(crate) fn is_forked_mode(&self) -> bool {
253 self.ecx.db().is_forked_mode()
254 }
255
256 #[inline]
258 pub(crate) fn is_persistent(&self, account: &Address) -> bool {
259 self.ecx.db().is_persistent(account)
260 }
261}
262
263#[cold]
264fn precompile_error(address: &Address) -> Error {
265 fmt_err!("cannot use precompile {address} as an argument")
266}