1use crate::{Cheatcode, Cheatcodes, CheatcodesExecutor, CheatsCtxt, Result, Vm::*};
4use alloy_dyn_abi::{DynSolType, DynSolValue, Resolver, TypedData, eip712_parser::EncodeType};
5use alloy_ens::namehash;
6use alloy_primitives::{B64, Bytes, I256, U256, aliases::B32, keccak256, map::HashMap};
7use alloy_rlp::{Decodable, Encodable};
8use alloy_sol_types::SolValue;
9use foundry_common::{TYPE_BINDING_PREFIX, fs};
10use foundry_config::fs_permissions::FsAccessKind;
11use foundry_evm_core::{constants::DEFAULT_CREATE2_DEPLOYER, evm::FoundryEvmNetwork};
12use foundry_evm_fuzz::strategies::BoundMutator;
13use proptest::prelude::Strategy;
14use rand::{Rng, RngCore, seq::SliceRandom};
15use revm::context::{ContextTr, JournalTr};
16use std::path::PathBuf;
17
18#[derive(Debug, Default, Clone)]
24pub struct IgnoredTraces {
25 pub ignored: HashMap<(usize, usize), (usize, usize)>,
28 pub last_pause_call: Option<(usize, usize)>,
30}
31
32impl Cheatcode for labelCall {
33 fn apply<FEN: FoundryEvmNetwork>(&self, state: &mut Cheatcodes<FEN>) -> Result {
34 let Self { account, newLabel } = self;
35 state.labels.insert(*account, newLabel.clone());
36 Ok(Default::default())
37 }
38}
39
40impl Cheatcode for getLabelCall {
41 fn apply<FEN: FoundryEvmNetwork>(&self, state: &mut Cheatcodes<FEN>) -> Result {
42 let Self { account } = self;
43 Ok(match state.labels.get(account) {
44 Some(label) => label.abi_encode(),
45 None => format!("unlabeled:{account}").abi_encode(),
46 })
47 }
48}
49
50impl Cheatcode for computeCreateAddressCall {
51 fn apply<FEN: FoundryEvmNetwork>(&self, _state: &mut Cheatcodes<FEN>) -> Result {
52 let Self { nonce, deployer } = self;
53 ensure!(*nonce <= U256::from(u64::MAX), "nonce must be less than 2^64");
54 Ok(deployer.create(nonce.to()).abi_encode())
55 }
56}
57
58impl Cheatcode for computeCreate2Address_0Call {
59 fn apply<FEN: FoundryEvmNetwork>(&self, _state: &mut Cheatcodes<FEN>) -> Result {
60 let Self { salt, initCodeHash, deployer } = self;
61 Ok(deployer.create2(salt, initCodeHash).abi_encode())
62 }
63}
64
65impl Cheatcode for computeCreate2Address_1Call {
66 fn apply<FEN: FoundryEvmNetwork>(&self, _state: &mut Cheatcodes<FEN>) -> Result {
67 let Self { salt, initCodeHash } = self;
68 Ok(DEFAULT_CREATE2_DEPLOYER.create2(salt, initCodeHash).abi_encode())
69 }
70}
71
72impl Cheatcode for ensNamehashCall {
73 fn apply<FEN: FoundryEvmNetwork>(&self, _state: &mut Cheatcodes<FEN>) -> Result {
74 let Self { name } = self;
75 Ok(namehash(name).abi_encode())
76 }
77}
78
79impl Cheatcode for bound_0Call {
80 fn apply<FEN: FoundryEvmNetwork>(&self, state: &mut Cheatcodes<FEN>) -> Result {
81 let Self { current, min, max } = *self;
82 let Some(mutated) = U256::bound(current, min, max, state.test_runner()) else {
83 bail!("cannot bound {current} in [{min}, {max}] range")
84 };
85 Ok(mutated.abi_encode())
86 }
87}
88
89impl Cheatcode for bound_1Call {
90 fn apply<FEN: FoundryEvmNetwork>(&self, state: &mut Cheatcodes<FEN>) -> Result {
91 let Self { current, min, max } = *self;
92 let Some(mutated) = I256::bound(current, min, max, state.test_runner()) else {
93 bail!("cannot bound {current} in [{min}, {max}] range")
94 };
95 Ok(mutated.abi_encode())
96 }
97}
98
99impl Cheatcode for randomUint_0Call {
100 fn apply<FEN: FoundryEvmNetwork>(&self, state: &mut Cheatcodes<FEN>) -> Result {
101 random_uint(state, None, None)
102 }
103}
104
105impl Cheatcode for randomUint_1Call {
106 fn apply<FEN: FoundryEvmNetwork>(&self, state: &mut Cheatcodes<FEN>) -> Result {
107 let Self { min, max } = *self;
108 random_uint(state, None, Some((min, max)))
109 }
110}
111
112impl Cheatcode for randomUint_2Call {
113 fn apply<FEN: FoundryEvmNetwork>(&self, state: &mut Cheatcodes<FEN>) -> Result {
114 let Self { bits } = *self;
115 random_uint(state, Some(bits), None)
116 }
117}
118
119impl Cheatcode for randomAddressCall {
120 fn apply<FEN: FoundryEvmNetwork>(&self, state: &mut Cheatcodes<FEN>) -> Result {
121 Ok(DynSolType::Address
122 .value_strategy()
123 .new_tree(state.test_runner())
124 .unwrap()
125 .current()
126 .abi_encode())
127 }
128}
129
130impl Cheatcode for randomInt_0Call {
131 fn apply<FEN: FoundryEvmNetwork>(&self, state: &mut Cheatcodes<FEN>) -> Result {
132 random_int(state, None)
133 }
134}
135
136impl Cheatcode for randomInt_1Call {
137 fn apply<FEN: FoundryEvmNetwork>(&self, state: &mut Cheatcodes<FEN>) -> Result {
138 let Self { bits } = *self;
139 random_int(state, Some(bits))
140 }
141}
142
143impl Cheatcode for randomBoolCall {
144 fn apply<FEN: FoundryEvmNetwork>(&self, state: &mut Cheatcodes<FEN>) -> Result {
145 let rand_bool: bool = state.rng().random();
146 Ok(rand_bool.abi_encode())
147 }
148}
149
150impl Cheatcode for randomBytesCall {
151 fn apply<FEN: FoundryEvmNetwork>(&self, state: &mut Cheatcodes<FEN>) -> Result {
152 let Self { len } = *self;
153 let len = usize::try_from(len)
154 .map_err(|_| fmt_err!("bytes length cannot exceed {}", usize::MAX))?;
155 let mut bytes = vec![0u8; len];
156 state.rng().fill_bytes(&mut bytes);
157 Ok(bytes.abi_encode())
158 }
159}
160
161impl Cheatcode for randomBytes4Call {
162 fn apply<FEN: FoundryEvmNetwork>(&self, state: &mut Cheatcodes<FEN>) -> Result {
163 let rand_u32 = state.rng().next_u32();
164 Ok(B32::from(rand_u32).abi_encode())
165 }
166}
167
168impl Cheatcode for randomBytes8Call {
169 fn apply<FEN: FoundryEvmNetwork>(&self, state: &mut Cheatcodes<FEN>) -> Result {
170 let rand_u64 = state.rng().next_u64();
171 Ok(B64::from(rand_u64).abi_encode())
172 }
173}
174
175impl Cheatcode for pauseTracingCall {
176 fn apply_full<FEN: FoundryEvmNetwork>(
177 &self,
178 ccx: &mut CheatsCtxt<'_, '_, FEN>,
179 executor: &mut dyn CheatcodesExecutor<FEN>,
180 ) -> Result {
181 let Some(tracer) = executor.tracing_inspector() else {
182 return Ok(Default::default());
184 };
185
186 if ccx.state.ignored_traces.last_pause_call.is_some() {
188 return Ok(Default::default());
189 }
190
191 let cur_node = &tracer.traces().nodes().last().expect("no trace nodes");
192 ccx.state.ignored_traces.last_pause_call = Some((cur_node.idx, cur_node.ordering.len()));
193
194 Ok(Default::default())
195 }
196}
197
198impl Cheatcode for resumeTracingCall {
199 fn apply_full<FEN: FoundryEvmNetwork>(
200 &self,
201 ccx: &mut CheatsCtxt<'_, '_, FEN>,
202 executor: &mut dyn CheatcodesExecutor<FEN>,
203 ) -> Result {
204 let Some(tracer) = executor.tracing_inspector() else {
205 return Ok(Default::default());
207 };
208
209 let Some(start) = ccx.state.ignored_traces.last_pause_call.take() else {
210 return Ok(Default::default());
212 };
213
214 let node = &tracer.traces().nodes().last().expect("no trace nodes");
215 ccx.state.ignored_traces.ignored.insert(start, (node.idx, node.ordering.len()));
216
217 Ok(Default::default())
218 }
219}
220
221impl Cheatcode for interceptInitcodeCall {
222 fn apply<FEN: FoundryEvmNetwork>(&self, state: &mut Cheatcodes<FEN>) -> Result {
223 let Self {} = self;
224 if state.intercept_next_create_call {
225 bail!("vm.interceptInitcode() has already been called")
226 }
227 state.intercept_next_create_call = true;
228 Ok(Default::default())
229 }
230}
231
232impl Cheatcode for setArbitraryStorage_0Call {
233 fn apply_stateful<FEN: FoundryEvmNetwork>(&self, ccx: &mut CheatsCtxt<'_, '_, FEN>) -> Result {
234 let Self { target } = self;
235 ccx.state.arbitrary_storage().mark_arbitrary(target, false);
236
237 Ok(Default::default())
238 }
239}
240
241impl Cheatcode for setArbitraryStorage_1Call {
242 fn apply_stateful<FEN: FoundryEvmNetwork>(&self, ccx: &mut CheatsCtxt<'_, '_, FEN>) -> Result {
243 let Self { target, overwrite } = self;
244 ccx.state.arbitrary_storage().mark_arbitrary(target, *overwrite);
245
246 Ok(Default::default())
247 }
248}
249
250impl Cheatcode for copyStorageCall {
251 fn apply_stateful<FEN: FoundryEvmNetwork>(&self, ccx: &mut CheatsCtxt<'_, '_, FEN>) -> Result {
252 let Self { from, to } = self;
253
254 ensure!(
255 !ccx.state.has_arbitrary_storage(to),
256 "target address cannot have arbitrary storage"
257 );
258
259 if let Ok(from_account) = ccx.ecx.journal_mut().load_account(*from) {
260 let from_storage = from_account.storage.clone();
261 if ccx.ecx.journal_mut().load_account(*to).is_ok() {
262 ccx.ecx.journal_mut().evm_state_mut().get_mut(to).unwrap().storage = from_storage;
264 if let Some(arbitrary_storage) = &mut ccx.state.arbitrary_storage {
265 arbitrary_storage.mark_copy(from, to);
266 }
267 }
268 }
269
270 Ok(Default::default())
271 }
272}
273
274impl Cheatcode for sortCall {
275 fn apply<FEN: FoundryEvmNetwork>(&self, _state: &mut Cheatcodes<FEN>) -> Result {
276 let Self { array } = self;
277
278 let mut sorted_values = array.clone();
279 sorted_values.sort();
280
281 Ok(sorted_values.abi_encode())
282 }
283}
284
285impl Cheatcode for shuffleCall {
286 fn apply<FEN: FoundryEvmNetwork>(&self, state: &mut Cheatcodes<FEN>) -> Result {
287 let Self { array } = self;
288
289 let mut shuffled_values = array.clone();
290 let rng = state.rng();
291 shuffled_values.shuffle(rng);
292
293 Ok(shuffled_values.abi_encode())
294 }
295}
296
297impl Cheatcode for setSeedCall {
298 fn apply_stateful<FEN: FoundryEvmNetwork>(&self, ccx: &mut CheatsCtxt<'_, '_, FEN>) -> Result {
299 let Self { seed } = self;
300 ccx.state.set_seed(*seed);
301 Ok(Default::default())
302 }
303}
304
305fn random_uint<FEN: FoundryEvmNetwork>(
306 state: &mut Cheatcodes<FEN>,
307 bits: Option<U256>,
308 bounds: Option<(U256, U256)>,
309) -> Result {
310 if let Some(bits) = bits {
311 let bits = usize::try_from(bits)
312 .ok()
313 .filter(|bits| *bits <= 256)
314 .ok_or_else(|| fmt_err!("number of bits cannot exceed 256"))?;
315 return Ok(DynSolValue::type_strategy(&DynSolType::Uint(bits))
316 .new_tree(state.test_runner())
317 .unwrap()
318 .current()
319 .abi_encode());
320 }
321
322 if let Some((min, max)) = bounds {
323 ensure!(min <= max, "min must be less than or equal to max");
324 let exclusive_modulo = max - min;
325 let mut random_number: U256 = state.rng().random();
326 if exclusive_modulo != U256::MAX {
327 let inclusive_modulo = exclusive_modulo + U256::ONE;
328 random_number %= inclusive_modulo;
329 }
330 random_number += min;
331 return Ok(random_number.abi_encode());
332 }
333
334 Ok(DynSolType::Uint(256)
335 .value_strategy()
336 .new_tree(state.test_runner())
337 .unwrap()
338 .current()
339 .abi_encode())
340}
341
342fn random_int<FEN: FoundryEvmNetwork>(state: &mut Cheatcodes<FEN>, bits: Option<U256>) -> Result {
343 let bits = bits.unwrap_or(U256::from(256));
344 let bits = usize::try_from(bits)
345 .ok()
346 .filter(|bits| *bits <= 256)
347 .ok_or_else(|| fmt_err!("number of bits cannot exceed 256"))?;
348 Ok(DynSolValue::type_strategy(&DynSolType::Int(bits))
349 .new_tree(state.test_runner())
350 .unwrap()
351 .current()
352 .abi_encode())
353}
354
355impl Cheatcode for eip712HashType_0Call {
356 fn apply<FEN: FoundryEvmNetwork>(&self, state: &mut Cheatcodes<FEN>) -> Result {
357 let Self { typeNameOrDefinition } = self;
358
359 let type_def = get_canonical_type_def(typeNameOrDefinition, state, None)?;
360
361 Ok(keccak256(type_def.as_bytes()).to_vec())
362 }
363}
364
365impl Cheatcode for eip712HashType_1Call {
366 fn apply<FEN: FoundryEvmNetwork>(&self, state: &mut Cheatcodes<FEN>) -> Result {
367 let Self { bindingsPath, typeName } = self;
368
369 let path = state.config.ensure_path_allowed(bindingsPath, FsAccessKind::Read)?;
370 let type_def = get_type_def_from_bindings(typeName, path, &state.config.root)?;
371
372 Ok(keccak256(type_def.as_bytes()).to_vec())
373 }
374}
375
376impl Cheatcode for eip712HashStruct_0Call {
377 fn apply<FEN: FoundryEvmNetwork>(&self, state: &mut Cheatcodes<FEN>) -> Result {
378 let Self { typeNameOrDefinition, abiEncodedData } = self;
379
380 let type_def = get_canonical_type_def(typeNameOrDefinition, state, None)?;
381 let primary = &type_def[..type_def.find('(').unwrap_or(type_def.len())];
382
383 get_struct_hash(primary, &type_def, abiEncodedData)
384 }
385}
386
387impl Cheatcode for eip712HashStruct_1Call {
388 fn apply<FEN: FoundryEvmNetwork>(&self, state: &mut Cheatcodes<FEN>) -> Result {
389 let Self { bindingsPath, typeName, abiEncodedData } = self;
390
391 let path = state.config.ensure_path_allowed(bindingsPath, FsAccessKind::Read)?;
392 let type_def = get_type_def_from_bindings(typeName, path, &state.config.root)?;
393
394 get_struct_hash(typeName, &type_def, abiEncodedData)
395 }
396}
397
398impl Cheatcode for eip712HashTypedDataCall {
399 fn apply<FEN: FoundryEvmNetwork>(&self, _state: &mut Cheatcodes<FEN>) -> Result {
400 let Self { jsonData } = self;
401 let typed_data: TypedData = serde_json::from_str(jsonData)?;
402 let digest = typed_data.eip712_signing_hash()?;
403
404 Ok(digest.to_vec())
405 }
406}
407
408fn get_canonical_type_def<FEN: FoundryEvmNetwork>(
411 name_or_def: &String,
412 state: &mut Cheatcodes<FEN>,
413 path: Option<PathBuf>,
414) -> Result<String> {
415 let type_def = if name_or_def.contains('(') {
416 EncodeType::parse(name_or_def).and_then(|parsed| parsed.canonicalize())?
418 } else {
419 let path = path.as_ref().unwrap_or(&state.config.bind_json_path);
421 let path = state.config.ensure_path_allowed(path, FsAccessKind::Read)?;
422 get_type_def_from_bindings(name_or_def, path, &state.config.root)?
423 };
424
425 Ok(type_def)
426}
427
428fn get_type_def_from_bindings(name: &String, path: PathBuf, root: &PathBuf) -> Result<String> {
431 let content = fs::read_to_string(&path)?;
432
433 let type_defs: HashMap<&str, &str> = content
434 .lines()
435 .filter_map(|line| {
436 let relevant = line.trim().strip_prefix(TYPE_BINDING_PREFIX)?;
437 let (name, def) = relevant.split_once('=')?;
438 Some((name.trim(), def.trim().strip_prefix('"')?.strip_suffix("\";")?))
439 })
440 .collect();
441
442 match type_defs.get(name.as_str()) {
443 Some(value) => Ok(value.to_string()),
444 None => {
445 let bindings =
446 type_defs.keys().map(|k| format!(" - {k}")).collect::<Vec<String>>().join("\n");
447
448 bail!(
449 "'{}' not found in '{}'.{}",
450 name,
451 path.strip_prefix(root).unwrap_or(&path).to_string_lossy(),
452 if bindings.is_empty() {
453 String::new()
454 } else {
455 format!("\nAvailable bindings:\n{bindings}\n")
456 }
457 );
458 }
459 }
460}
461
462fn get_struct_hash(primary: &str, type_def: &String, abi_encoded_data: &Bytes) -> Result {
464 let mut resolver = Resolver::default();
465
466 resolver
469 .ingest_string(type_def)
470 .map_err(|e| fmt_err!("Resolver failed to ingest type definition: {e}"))?;
471
472 let resolved_sol_type = resolver
473 .resolve(primary)
474 .map_err(|e| fmt_err!("Failed to resolve EIP-712 primary type '{primary}': {e}"))?;
475
476 let sol_value = resolved_sol_type.abi_decode(abi_encoded_data.as_ref()).map_err(|e| {
478 fmt_err!("Failed to ABI decode using resolved_sol_type directly for '{primary}': {e}.")
479 })?;
480
481 let encoded_data: Vec<u8> = resolver
483 .encode_data(&sol_value)
484 .map_err(|e| fmt_err!("Failed to EIP-712 encode data for struct '{primary}': {e}"))?
485 .ok_or_else(|| fmt_err!("EIP-712 data encoding returned 'None' for struct '{primary}'"))?;
486
487 let type_hash = resolver
489 .type_hash(primary)
490 .map_err(|e| fmt_err!("Failed to compute typeHash for EIP712 type '{primary}': {e}"))?;
491
492 let mut bytes_to_hash = Vec::with_capacity(32 + encoded_data.len());
494 bytes_to_hash.extend_from_slice(type_hash.as_slice());
495 bytes_to_hash.extend_from_slice(&encoded_data);
496
497 Ok(keccak256(&bytes_to_hash).to_vec())
498}
499
500impl Cheatcode for toRlpCall {
501 fn apply<FEN: FoundryEvmNetwork>(&self, _state: &mut Cheatcodes<FEN>) -> Result {
502 let Self { data } = self;
503
504 let mut buf = Vec::new();
505 data.encode(&mut buf);
506
507 Ok(Bytes::from(buf).abi_encode())
508 }
509}
510
511impl Cheatcode for fromRlpCall {
512 fn apply<FEN: FoundryEvmNetwork>(&self, _state: &mut Cheatcodes<FEN>) -> Result {
513 let Self { rlp } = self;
514
515 let decoded: Vec<Bytes> = Vec::<Bytes>::decode(&mut rlp.as_ref())
516 .map_err(|e| fmt_err!("Failed to decode RLP: {e}"))?;
517
518 Ok(decoded.abi_encode())
519 }
520}