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;
12use foundry_evm_fuzz::strategies::BoundMutator;
13use proptest::prelude::Strategy;
14use rand::{Rng, RngCore, seq::SliceRandom};
15use revm::context::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(&self, state: &mut Cheatcodes) -> 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(&self, state: &mut Cheatcodes) -> 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(&self, _state: &mut Cheatcodes) -> 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(&self, _state: &mut Cheatcodes) -> 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(&self, _state: &mut Cheatcodes) -> 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(&self, _state: &mut Cheatcodes) -> Result {
74 let Self { name } = self;
75 Ok(namehash(name).abi_encode())
76 }
77}
78
79impl Cheatcode for bound_0Call {
80 fn apply(&self, state: &mut Cheatcodes) -> 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(&self, state: &mut Cheatcodes) -> 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(&self, state: &mut Cheatcodes) -> Result {
101 random_uint(state, None, None)
102 }
103}
104
105impl Cheatcode for randomUint_1Call {
106 fn apply(&self, state: &mut Cheatcodes) -> 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(&self, state: &mut Cheatcodes) -> Result {
114 let Self { bits } = *self;
115 random_uint(state, Some(bits), None)
116 }
117}
118
119impl Cheatcode for randomAddressCall {
120 fn apply(&self, state: &mut Cheatcodes) -> Result {
121 Ok(DynSolValue::type_strategy(&DynSolType::Address)
122 .new_tree(state.test_runner())
123 .unwrap()
124 .current()
125 .abi_encode())
126 }
127}
128
129impl Cheatcode for randomInt_0Call {
130 fn apply(&self, state: &mut Cheatcodes) -> Result {
131 random_int(state, None)
132 }
133}
134
135impl Cheatcode for randomInt_1Call {
136 fn apply(&self, state: &mut Cheatcodes) -> Result {
137 let Self { bits } = *self;
138 random_int(state, Some(bits))
139 }
140}
141
142impl Cheatcode for randomBoolCall {
143 fn apply(&self, state: &mut Cheatcodes) -> Result {
144 let rand_bool: bool = state.rng().random();
145 Ok(rand_bool.abi_encode())
146 }
147}
148
149impl Cheatcode for randomBytesCall {
150 fn apply(&self, state: &mut Cheatcodes) -> Result {
151 let Self { len } = *self;
152 ensure!(
153 len <= U256::from(usize::MAX),
154 format!("bytes length cannot exceed {}", usize::MAX)
155 );
156 let mut bytes = vec![0u8; len.to::<usize>()];
157 state.rng().fill_bytes(&mut bytes);
158 Ok(bytes.abi_encode())
159 }
160}
161
162impl Cheatcode for randomBytes4Call {
163 fn apply(&self, state: &mut Cheatcodes) -> Result {
164 let rand_u32 = state.rng().next_u32();
165 Ok(B32::from(rand_u32).abi_encode())
166 }
167}
168
169impl Cheatcode for randomBytes8Call {
170 fn apply(&self, state: &mut Cheatcodes) -> Result {
171 let rand_u64 = state.rng().next_u64();
172 Ok(B64::from(rand_u64).abi_encode())
173 }
174}
175
176impl Cheatcode for pauseTracingCall {
177 fn apply_full(
178 &self,
179 ccx: &mut crate::CheatsCtxt,
180 executor: &mut dyn CheatcodesExecutor,
181 ) -> Result {
182 let Some(tracer) = executor.tracing_inspector() else {
183 return Ok(Default::default());
185 };
186
187 if ccx.state.ignored_traces.last_pause_call.is_some() {
189 return Ok(Default::default());
190 }
191
192 let cur_node = &tracer.traces().nodes().last().expect("no trace nodes");
193 ccx.state.ignored_traces.last_pause_call = Some((cur_node.idx, cur_node.ordering.len()));
194
195 Ok(Default::default())
196 }
197}
198
199impl Cheatcode for resumeTracingCall {
200 fn apply_full(
201 &self,
202 ccx: &mut crate::CheatsCtxt,
203 executor: &mut dyn CheatcodesExecutor,
204 ) -> Result {
205 let Some(tracer) = executor.tracing_inspector() else {
206 return Ok(Default::default());
208 };
209
210 let Some(start) = ccx.state.ignored_traces.last_pause_call.take() else {
211 return Ok(Default::default());
213 };
214
215 let node = &tracer.traces().nodes().last().expect("no trace nodes");
216 ccx.state.ignored_traces.ignored.insert(start, (node.idx, node.ordering.len()));
217
218 Ok(Default::default())
219 }
220}
221
222impl Cheatcode for interceptInitcodeCall {
223 fn apply(&self, state: &mut Cheatcodes) -> Result {
224 let Self {} = self;
225 if !state.intercept_next_create_call {
226 state.intercept_next_create_call = true;
227 } else {
228 bail!("vm.interceptInitcode() has already been called")
229 }
230 Ok(Default::default())
231 }
232}
233
234impl Cheatcode for setArbitraryStorage_0Call {
235 fn apply_stateful(&self, ccx: &mut CheatsCtxt) -> Result {
236 let Self { target } = self;
237 ccx.state.arbitrary_storage().mark_arbitrary(target, false);
238
239 Ok(Default::default())
240 }
241}
242
243impl Cheatcode for setArbitraryStorage_1Call {
244 fn apply_stateful(&self, ccx: &mut CheatsCtxt) -> Result {
245 let Self { target, overwrite } = self;
246 ccx.state.arbitrary_storage().mark_arbitrary(target, *overwrite);
247
248 Ok(Default::default())
249 }
250}
251
252impl Cheatcode for copyStorageCall {
253 fn apply_stateful(&self, ccx: &mut CheatsCtxt) -> Result {
254 let Self { from, to } = self;
255
256 ensure!(
257 !ccx.state.has_arbitrary_storage(to),
258 "target address cannot have arbitrary storage"
259 );
260
261 if let Ok(from_account) = ccx.ecx.journaled_state.load_account(*from) {
262 let from_storage = from_account.storage.clone();
263 if let Ok(mut to_account) = ccx.ecx.journaled_state.load_account(*to) {
264 to_account.storage = from_storage;
265 if let Some(arbitrary_storage) = &mut ccx.state.arbitrary_storage {
266 arbitrary_storage.mark_copy(from, to);
267 }
268 }
269 }
270
271 Ok(Default::default())
272 }
273}
274
275impl Cheatcode for sortCall {
276 fn apply(&self, _state: &mut Cheatcodes) -> Result {
277 let Self { array } = self;
278
279 let mut sorted_values = array.clone();
280 sorted_values.sort();
281
282 Ok(sorted_values.abi_encode())
283 }
284}
285
286impl Cheatcode for shuffleCall {
287 fn apply(&self, state: &mut Cheatcodes) -> Result {
288 let Self { array } = self;
289
290 let mut shuffled_values = array.clone();
291 let rng = state.rng();
292 shuffled_values.shuffle(rng);
293
294 Ok(shuffled_values.abi_encode())
295 }
296}
297
298impl Cheatcode for setSeedCall {
299 fn apply_stateful(&self, ccx: &mut CheatsCtxt) -> Result {
300 let Self { seed } = self;
301 ccx.state.set_seed(*seed);
302 Ok(Default::default())
303 }
304}
305
306fn random_uint(state: &mut Cheatcodes, bits: Option<U256>, bounds: Option<(U256, U256)>) -> Result {
309 if let Some(bits) = bits {
310 ensure!(bits <= U256::from(256), "number of bits cannot exceed 256");
312 return Ok(DynSolValue::type_strategy(&DynSolType::Uint(bits.to::<usize>()))
313 .new_tree(state.test_runner())
314 .unwrap()
315 .current()
316 .abi_encode());
317 }
318
319 if let Some((min, max)) = bounds {
320 ensure!(min <= max, "min must be less than or equal to max");
321 let exclusive_modulo = max - min;
323 let mut random_number: U256 = state.rng().random();
324 if exclusive_modulo != U256::MAX {
325 let inclusive_modulo = exclusive_modulo + U256::from(1);
326 random_number %= inclusive_modulo;
327 }
328 random_number += min;
329 return Ok(random_number.abi_encode());
330 }
331
332 Ok(DynSolValue::type_strategy(&DynSolType::Uint(256))
334 .new_tree(state.test_runner())
335 .unwrap()
336 .current()
337 .abi_encode())
338}
339
340fn random_int(state: &mut Cheatcodes, bits: Option<U256>) -> Result {
342 let no_bits = bits.unwrap_or(U256::from(256));
343 ensure!(no_bits <= U256::from(256), "number of bits cannot exceed 256");
344 Ok(DynSolValue::type_strategy(&DynSolType::Int(no_bits.to::<usize>()))
345 .new_tree(state.test_runner())
346 .unwrap()
347 .current()
348 .abi_encode())
349}
350
351impl Cheatcode for eip712HashType_0Call {
352 fn apply(&self, state: &mut Cheatcodes) -> Result {
353 let Self { typeNameOrDefinition } = self;
354
355 let type_def = get_canonical_type_def(typeNameOrDefinition, state, None)?;
356
357 Ok(keccak256(type_def.as_bytes()).to_vec())
358 }
359}
360
361impl Cheatcode for eip712HashType_1Call {
362 fn apply(&self, state: &mut Cheatcodes) -> Result {
363 let Self { bindingsPath, typeName } = self;
364
365 let path = state.config.ensure_path_allowed(bindingsPath, FsAccessKind::Read)?;
366 let type_def = get_type_def_from_bindings(typeName, path, &state.config.root)?;
367
368 Ok(keccak256(type_def.as_bytes()).to_vec())
369 }
370}
371
372impl Cheatcode for eip712HashStruct_0Call {
373 fn apply(&self, state: &mut Cheatcodes) -> Result {
374 let Self { typeNameOrDefinition, abiEncodedData } = self;
375
376 let type_def = get_canonical_type_def(typeNameOrDefinition, state, None)?;
377 let primary = &type_def[..type_def.find('(').unwrap_or(type_def.len())];
378
379 get_struct_hash(primary, &type_def, abiEncodedData)
380 }
381}
382
383impl Cheatcode for eip712HashStruct_1Call {
384 fn apply(&self, state: &mut Cheatcodes) -> Result {
385 let Self { bindingsPath, typeName, abiEncodedData } = self;
386
387 let path = state.config.ensure_path_allowed(bindingsPath, FsAccessKind::Read)?;
388 let type_def = get_type_def_from_bindings(typeName, path, &state.config.root)?;
389
390 get_struct_hash(typeName, &type_def, abiEncodedData)
391 }
392}
393
394impl Cheatcode for eip712HashTypedDataCall {
395 fn apply(&self, _state: &mut Cheatcodes) -> Result {
396 let Self { jsonData } = self;
397 let typed_data: TypedData = serde_json::from_str(jsonData)?;
398 let digest = typed_data.eip712_signing_hash()?;
399
400 Ok(digest.to_vec())
401 }
402}
403
404fn get_canonical_type_def(
407 name_or_def: &String,
408 state: &mut Cheatcodes,
409 path: Option<PathBuf>,
410) -> Result<String> {
411 let type_def = if name_or_def.contains('(') {
412 EncodeType::parse(name_or_def).and_then(|parsed| parsed.canonicalize())?
414 } else {
415 let path = path.as_ref().unwrap_or(&state.config.bind_json_path);
417 let path = state.config.ensure_path_allowed(path, FsAccessKind::Read)?;
418 get_type_def_from_bindings(name_or_def, path, &state.config.root)?
419 };
420
421 Ok(type_def)
422}
423
424fn get_type_def_from_bindings(name: &String, path: PathBuf, root: &PathBuf) -> Result<String> {
427 let content = fs::read_to_string(&path)?;
428
429 let type_defs: HashMap<&str, &str> = content
430 .lines()
431 .filter_map(|line| {
432 let relevant = line.trim().strip_prefix(TYPE_BINDING_PREFIX)?;
433 let (name, def) = relevant.split_once('=')?;
434 Some((name.trim(), def.trim().strip_prefix('"')?.strip_suffix("\";")?))
435 })
436 .collect();
437
438 match type_defs.get(name.as_str()) {
439 Some(value) => Ok(value.to_string()),
440 None => {
441 let bindings =
442 type_defs.keys().map(|k| format!(" - {k}")).collect::<Vec<String>>().join("\n");
443
444 bail!(
445 "'{}' not found in '{}'.{}",
446 name,
447 path.strip_prefix(root).unwrap_or(&path).to_string_lossy(),
448 if bindings.is_empty() {
449 String::new()
450 } else {
451 format!("\nAvailable bindings:\n{bindings}\n")
452 }
453 );
454 }
455 }
456}
457
458fn get_struct_hash(primary: &str, type_def: &String, abi_encoded_data: &Bytes) -> Result {
460 let mut resolver = Resolver::default();
461
462 resolver
465 .ingest_string(type_def)
466 .map_err(|e| fmt_err!("Resolver failed to ingest type definition: {e}"))?;
467
468 let resolved_sol_type = resolver
469 .resolve(primary)
470 .map_err(|e| fmt_err!("Failed to resolve EIP-712 primary type '{primary}': {e}"))?;
471
472 let sol_value = resolved_sol_type.abi_decode(abi_encoded_data.as_ref()).map_err(|e| {
474 fmt_err!("Failed to ABI decode using resolved_sol_type directly for '{primary}': {e}.")
475 })?;
476
477 let encoded_data: Vec<u8> = resolver
479 .encode_data(&sol_value)
480 .map_err(|e| fmt_err!("Failed to EIP-712 encode data for struct '{primary}': {e}"))?
481 .ok_or_else(|| fmt_err!("EIP-712 data encoding returned 'None' for struct '{primary}'"))?;
482
483 let type_hash = resolver
485 .type_hash(primary)
486 .map_err(|e| fmt_err!("Failed to compute typeHash for EIP712 type '{primary}': {e}"))?;
487
488 let mut bytes_to_hash = Vec::with_capacity(32 + encoded_data.len());
490 bytes_to_hash.extend_from_slice(type_hash.as_slice());
491 bytes_to_hash.extend_from_slice(&encoded_data);
492
493 Ok(keccak256(&bytes_to_hash).to_vec())
494}
495
496impl Cheatcode for toRlpCall {
497 fn apply(&self, _state: &mut Cheatcodes) -> Result {
498 let Self { data } = self;
499
500 let mut buf = Vec::new();
501 data.encode(&mut buf);
502
503 Ok(Bytes::from(buf).abi_encode())
504 }
505}
506
507impl Cheatcode for fromRlpCall {
508 fn apply(&self, _state: &mut Cheatcodes) -> Result {
509 let Self { rlp } = self;
510
511 let decoded: Vec<Bytes> = Vec::<Bytes>::decode(&mut rlp.as_ref())
512 .map_err(|e| fmt_err!("Failed to decode RLP: {e}"))?;
513
514 Ok(decoded.abi_encode())
515 }
516}