1use super::*;
2
3impl SymbolicExecutor {
4 pub(super) fn handle_assertion(
6 &mut self,
7 state: &mut PathState,
8 pass: BoolExpr,
9 ) -> Result<CheatcodeOutcome, SymbolicError> {
10 let fail = pass.clone().not();
11 match fail {
12 BoolExpr::Const(true) => return Ok(CheatcodeOutcome::Failure),
13 BoolExpr::Const(false) => return Ok(CheatcodeOutcome::Continue(Vec::new())),
14 _ => {}
15 }
16
17 if bool_contains_gasleft(&pass) {
18 return Err(SymbolicError::Unsupported("GAS/gasleft() not modeled"));
19 }
20
21 let mut fail_constraints = state.constraints.clone();
22 fail_constraints.push(fail);
23 if self.solver.is_sat(&fail_constraints)? {
24 state.constraints = fail_constraints;
25 return Ok(CheatcodeOutcome::Failure);
26 }
27
28 state.constraints.push(pass);
29 Ok(CheatcodeOutcome::Continue(Vec::new()))
30 }
31
32 pub(super) fn set_expected_revert(
34 &mut self,
35 state: &mut PathState,
36 data: ExpectedRevertData,
37 reverter: Option<SymWord>,
38 remaining: u64,
39 ) -> CheatcodeOutcome {
40 state.expected_revert =
41 Some(ExpectedRevert { data, reverter, remaining: remaining.max(1) });
42 CheatcodeOutcome::Continue(Vec::new())
43 }
44
45 pub(super) fn set_expected_emit(
47 &mut self,
48 state: &mut PathState,
49 checks: ExpectedEmitChecks,
50 emitter: Option<SymWord>,
51 remaining: u64,
52 ) -> CheatcodeOutcome {
53 state.expected_emit =
54 Some(ExpectedEmit { checks, emitter, remaining: remaining.max(1), template: None });
55 CheatcodeOutcome::Continue(Vec::new())
56 }
57
58 #[expect(clippy::too_many_arguments)]
59 pub(super) fn set_expected_call(
61 &mut self,
62 state: &mut PathState,
63 callee: SymWord,
64 value: Option<U256>,
65 gas: Option<u64>,
66 min_gas: Option<u64>,
67 data: Vec<SymWord>,
68 count: Option<u64>,
69 ) -> CheatcodeOutcome {
70 let (gas, min_gas) = adjust_expected_call_gas_for_value(value, gas, min_gas);
71 state.expected_calls.push(ExpectedCall {
72 callee,
73 value,
74 gas,
75 min_gas,
76 data,
77 expected: count.unwrap_or(1).max(1),
78 observed: 0,
79 exact: count.is_some(),
80 });
81 CheatcodeOutcome::Continue(Vec::new())
82 }
83
84 pub(super) fn set_expected_create(
86 &mut self,
87 state: &mut PathState,
88 bytecode: Vec<u8>,
89 deployer: SymWord,
90 kind: CreateKind,
91 ) -> CheatcodeOutcome {
92 state.expected_creates.push(ExpectedCreate { bytecode, deployer, kind });
93 CheatcodeOutcome::Continue(Vec::new())
94 }
95
96 pub(super) fn observe_expected_create(
98 &mut self,
99 state: &mut PathState,
100 deployer: Address,
101 kind: CreateKind,
102 runtime: &SymReturnData,
103 ) -> Result<(), SymbolicError> {
104 if state.expected_creates.is_empty() {
105 return Ok(());
106 }
107 let bytecode = runtime.read_concrete("symbolic expected create bytecode")?;
108 let mut mismatch_constraints = None;
109 for idx in 0..state.expected_creates.len() {
110 let expected = state.expected_creates[idx].clone();
111 if expected.kind != kind || expected.bytecode != bytecode {
112 continue;
113 }
114
115 let condition = address_match_condition(&expected.deployer, deployer);
116 let (match_constraints, match_sat) =
117 self.constraints_with_condition(state, condition.clone())?;
118 let (candidate_mismatch_constraints, mismatch_sat) =
119 self.constraints_with_condition(state, condition.not())?;
120
121 if match_sat && !mismatch_sat {
122 state.constraints = match_constraints;
123 state.expected_creates.swap_remove(idx);
124 return Ok(());
125 }
126
127 if mismatch_sat {
128 mismatch_constraints.get_or_insert(candidate_mismatch_constraints);
129 }
130 }
131
132 if let Some(constraints) = mismatch_constraints {
133 state.constraints = constraints;
134 }
135 Ok(())
136 }
137
138 pub(super) fn branch_accesses_cheatcode_if_needed(
140 &mut self,
141 state: &mut PathState,
142 worklist: &mut VecDeque<PathState>,
143 selector: [u8; 4],
144 in_offset: usize,
145 out_offset: SymWord,
146 out_size: &BoundedCopySize,
147 ) -> Result<Option<StepOutcome>, SymbolicError> {
148 if selector != selector!("accesses(address)") {
149 return Ok(None);
150 }
151
152 let Some(record) = state.access_record.clone() else {
153 return Ok(None);
154 };
155 let target = read_abi_word_arg(&state.memory, in_offset + 4, 0)?;
156 if matches!(target, SymWord::Concrete(_)) {
157 return Ok(None);
158 }
159
160 let addresses =
161 record.reads.keys().chain(record.writes.keys()).copied().collect::<BTreeSet<_>>();
162 if addresses.is_empty() {
163 return Ok(None);
164 }
165
166 let mut branches = VecDeque::new();
167 let mut matched_conditions = Vec::new();
168 for address in addresses {
169 let condition = address_match_condition(&target, address);
170 matched_conditions.push(condition.clone());
171 if let Some(constraints) = self.constraints_for_condition(state, condition)? {
172 let mut branch = state.clone();
173 branch.constraints = constraints;
174 complete_cheatcode_call(
175 &mut branch,
176 out_offset.clone(),
177 out_size,
178 accesses_return_data(Some(&record), address),
179 )?;
180 branches.push_back(branch);
181 }
182 }
183
184 let unmatched_condition =
185 BoolExpr::and(matched_conditions.into_iter().map(BoolExpr::not).collect());
186 if let Some(constraints) = self.constraints_for_condition(state, unmatched_condition)? {
187 let mut branch = state.clone();
188 branch.constraints = constraints;
189 complete_cheatcode_call(
190 &mut branch,
191 out_offset,
192 out_size,
193 accesses_return_data(Some(&record), Address::ZERO),
194 )?;
195 branches.push_back(branch);
196 }
197
198 let Some(first_branch) = pop_batch(&mut branches, self.config.exploration_order) else {
199 return Ok(Some(StepOutcome::AssumeRejected));
200 };
201 *state = first_branch;
202 spill_batch(branches, worklist, self.config.exploration_order);
203 Ok(Some(StepOutcome::Continue))
204 }
205
206 pub(super) fn accesses_return_data_for_target(
208 &mut self,
209 state: &mut PathState,
210 target: SymWord,
211 ) -> Result<SymReturnData, SymbolicError> {
212 let Some(record) = state.access_record.clone() else {
213 return Ok(accesses_return_data(None, Address::ZERO));
214 };
215
216 if let SymWord::Concrete(target) = target {
217 return Ok(accesses_return_data(Some(&record), word_to_address(target)));
218 }
219
220 let addresses =
221 record.reads.keys().chain(record.writes.keys()).copied().collect::<BTreeSet<_>>();
222 if addresses.is_empty() {
223 return Ok(accesses_return_data(Some(&record), Address::ZERO));
224 }
225
226 for address in addresses {
227 let condition = address_match_condition(&target, address);
228 let (match_constraints, match_sat) =
229 self.constraints_with_condition(state, condition.clone())?;
230 let (_, mismatch_sat) = self.constraints_with_condition(state, condition.not())?;
231
232 match (match_sat, mismatch_sat) {
233 (true, false) => {
234 state.constraints = match_constraints;
235 return Ok(accesses_return_data(Some(&record), address));
236 }
237 (true, true) => {
238 return Err(SymbolicError::Unsupported("symbolic vm.accesses address"));
239 }
240 (false, _) => {}
241 }
242 }
243
244 Ok(accesses_return_data(Some(&record), Address::ZERO))
245 }
246
247 pub(super) fn add_call_mock(
249 &mut self,
250 state: &mut PathState,
251 callee: SymWord,
252 value: Option<U256>,
253 data: Vec<SymWord>,
254 returns: Vec<SymReturnData>,
255 reverts: bool,
256 ) -> CheatcodeOutcome {
257 state.call_mocks.push(CallMock { callee, value, data, returns, reverts, calls: 0 });
258 CheatcodeOutcome::Continue(Vec::new())
259 }
260
261 pub(super) fn set_function_mock(
263 &mut self,
264 state: &mut PathState,
265 callee: SymWord,
266 target: Address,
267 data: Vec<SymWord>,
268 ) -> CheatcodeOutcome {
269 if let Some(mock) =
270 state.function_mocks.iter_mut().find(|mock| mock.callee == callee && mock.data == data)
271 {
272 mock.target = target;
273 } else {
274 state.function_mocks.push(FunctionMock { callee, target, data });
275 }
276 CheatcodeOutcome::Continue(Vec::new())
277 }
278
279 pub(super) fn handle_foundry_cheatcode<FEN: FoundryEvmNetwork>(
281 &mut self,
282 executor: &Executor<FEN>,
283 state: &mut PathState,
284 selector: [u8; 4],
285 in_offset: usize,
286 in_size: usize,
287 ) -> Result<CheatcodeOutcome, SymbolicError> {
288 let args_offset = in_offset + 4;
289 if selector == selector!("assume(bool)") {
290 return self.handle_assume(state, in_offset + 4);
291 }
292 if selector == selector!("assumeNoRevert()") {
293 if state.assume_no_revert_next_call.is_some() {
294 return Err(SymbolicError::Unsupported("symbolic vm.assumeNoRevert overlap"));
295 }
296 state.assume_no_revert_next_call = Some(AssumeNoRevert::Any);
297 return Ok(CheatcodeOutcome::Continue(Vec::new()));
298 }
299 if selector == selector!("assumeNoRevert((address,bool,bytes))") {
300 if state.assume_no_revert_next_call.is_some() {
301 return Err(SymbolicError::Unsupported("symbolic vm.assumeNoRevert overlap"));
302 }
303 let mut values = decode_cheatcode_args(
304 state,
305 in_offset,
306 in_size,
307 vec![DynSolType::Tuple(vec![
308 DynSolType::Address,
309 DynSolType::Bool,
310 DynSolType::Bytes,
311 ])],
312 )?;
313 let value = values
314 .pop()
315 .ok_or(SymbolicError::Unsupported("symbolic vm.assumeNoRevert decode"))?;
316 state.assume_no_revert_next_call =
317 Some(AssumeNoRevert::Filtered(vec![dyn_potential_revert(&value)?]));
318 return Ok(CheatcodeOutcome::Continue(Vec::new()));
319 }
320 if selector == selector!("assumeNoRevert((address,bool,bytes)[])") {
321 if state.assume_no_revert_next_call.is_some() {
322 return Err(SymbolicError::Unsupported("symbolic vm.assumeNoRevert overlap"));
323 }
324 let mut values = decode_cheatcode_args(
325 state,
326 in_offset,
327 in_size,
328 vec![DynSolType::Array(Box::new(DynSolType::Tuple(vec![
329 DynSolType::Address,
330 DynSolType::Bool,
331 DynSolType::Bytes,
332 ])))],
333 )?;
334 let value = values
335 .pop()
336 .ok_or(SymbolicError::Unsupported("symbolic vm.assumeNoRevert decode"))?;
337 state.assume_no_revert_next_call =
338 Some(AssumeNoRevert::Filtered(dyn_potential_reverts(&value)?));
339 return Ok(CheatcodeOutcome::Continue(Vec::new()));
340 }
341 if selector == selector!("skip(bool)") || selector == selector!("skip(bool,string)") {
342 return self.handle_skip(state, in_offset + 4);
343 }
344 if selector == selector!("recordLogs()") {
345 state.recorded_logs = Some(Vec::new());
346 return Ok(CheatcodeOutcome::Continue(Vec::new()));
347 }
348 if selector == selector!("record()") {
349 state.access_record = Some(AccessRecord::default());
350 return Ok(CheatcodeOutcome::Continue(Vec::new()));
351 }
352 if selector == selector!("stopRecord()") {
353 state.access_record = None;
354 return Ok(CheatcodeOutcome::Continue(Vec::new()));
355 }
356 if selector == selector!("accesses(address)") {
357 let target = read_abi_word_arg(&state.memory, args_offset, 0)?;
358 return Ok(CheatcodeOutcome::ContinueData(
359 self.accesses_return_data_for_target(state, target)?,
360 ));
361 }
362 if selector == selector!("getRecordedLogs()") {
363 let logs = state.recorded_logs.replace(Vec::new()).unwrap_or_default();
364 return Ok(CheatcodeOutcome::ContinueData(recorded_logs_return_data(logs)));
365 }
366 if selector == selector!("getRecordedLogsJson()") {
367 let logs = state.recorded_logs.replace(Vec::new()).unwrap_or_default();
368 return Ok(CheatcodeOutcome::ContinueData(recorded_logs_json_return_data(logs)?));
369 }
370 if selector == selector!("expectRevert()") {
371 return Ok(self.set_expected_revert(state, ExpectedRevertData::Any, None, 1));
372 }
373 if selector == selector!("expectRevert(bytes4)") {
374 let selector = read_abi_bytes4_words_arg(&state.memory, args_offset, 0);
375 return Ok(self.set_expected_revert(
376 state,
377 ExpectedRevertData::Prefix(selector),
378 None,
379 1,
380 ));
381 }
382 if selector == selector!("expectRevert(bytes)") {
383 let data = read_abi_symbolic_dynamic_bytes_arg(
384 state,
385 args_offset,
386 0,
387 self.config.max_calldata_bytes as usize,
388 "symbolic vm.expectRevert",
389 )?;
390 return Ok(self.set_expected_revert(state, ExpectedRevertData::Exact(data), None, 1));
391 }
392 if selector == selector!("expectRevert(address)") {
393 let reverter = read_abi_word_arg(&state.memory, args_offset, 0)?;
394 return Ok(self.set_expected_revert(state, ExpectedRevertData::Any, Some(reverter), 1));
395 }
396 if selector == selector!("expectRevert(bytes4,address)") {
397 let selector = read_abi_bytes4_words_arg(&state.memory, args_offset, 0);
398 let reverter = read_abi_word_arg(&state.memory, args_offset, 1)?;
399 return Ok(self.set_expected_revert(
400 state,
401 ExpectedRevertData::Prefix(selector),
402 Some(reverter),
403 1,
404 ));
405 }
406 if selector == selector!("expectRevert(bytes,address)") {
407 let data = read_abi_symbolic_dynamic_bytes_arg(
408 state,
409 args_offset,
410 0,
411 self.config.max_calldata_bytes as usize,
412 "symbolic vm.expectRevert",
413 )?;
414 let reverter = read_abi_word_arg(&state.memory, args_offset, 1)?;
415 return Ok(self.set_expected_revert(
416 state,
417 ExpectedRevertData::Exact(data),
418 Some(reverter),
419 1,
420 ));
421 }
422 if selector == selector!("expectRevert(uint64)") {
423 let count =
424 read_abi_u64_arg(&state.memory, args_offset, 0, "symbolic vm.expectRevert")?;
425 return Ok(self.set_expected_revert(state, ExpectedRevertData::Any, None, count));
426 }
427 if selector == selector!("expectRevert(bytes4,uint64)") {
428 let selector = read_abi_bytes4_words_arg(&state.memory, args_offset, 0);
429 let count =
430 read_abi_u64_arg(&state.memory, args_offset, 1, "symbolic vm.expectRevert")?;
431 return Ok(self.set_expected_revert(
432 state,
433 ExpectedRevertData::Prefix(selector),
434 None,
435 count,
436 ));
437 }
438 if selector == selector!("expectRevert(bytes,uint64)") {
439 let data = read_abi_symbolic_dynamic_bytes_arg(
440 state,
441 args_offset,
442 0,
443 self.config.max_calldata_bytes as usize,
444 "symbolic vm.expectRevert",
445 )?;
446 let count =
447 read_abi_u64_arg(&state.memory, args_offset, 1, "symbolic vm.expectRevert")?;
448 return Ok(self.set_expected_revert(
449 state,
450 ExpectedRevertData::Exact(data),
451 None,
452 count,
453 ));
454 }
455 if selector == selector!("expectRevert(address,uint64)") {
456 let reverter = read_abi_word_arg(&state.memory, args_offset, 0)?;
457 let count =
458 read_abi_u64_arg(&state.memory, args_offset, 1, "symbolic vm.expectRevert")?;
459 return Ok(self.set_expected_revert(
460 state,
461 ExpectedRevertData::Any,
462 Some(reverter),
463 count,
464 ));
465 }
466 if selector == selector!("expectRevert(bytes4,address,uint64)") {
467 let selector = read_abi_bytes4_words_arg(&state.memory, args_offset, 0);
468 let reverter = read_abi_word_arg(&state.memory, args_offset, 1)?;
469 let count =
470 read_abi_u64_arg(&state.memory, args_offset, 2, "symbolic vm.expectRevert")?;
471 return Ok(self.set_expected_revert(
472 state,
473 ExpectedRevertData::Prefix(selector),
474 Some(reverter),
475 count,
476 ));
477 }
478 if selector == selector!("expectRevert(bytes,address,uint64)") {
479 let data = read_abi_symbolic_dynamic_bytes_arg(
480 state,
481 args_offset,
482 0,
483 self.config.max_calldata_bytes as usize,
484 "symbolic vm.expectRevert",
485 )?;
486 let reverter = read_abi_word_arg(&state.memory, args_offset, 1)?;
487 let count =
488 read_abi_u64_arg(&state.memory, args_offset, 2, "symbolic vm.expectRevert")?;
489 return Ok(self.set_expected_revert(
490 state,
491 ExpectedRevertData::Exact(data),
492 Some(reverter),
493 count,
494 ));
495 }
496 if selector == selector!("expectPartialRevert(bytes4)") {
497 let selector = read_abi_bytes4_words_arg(&state.memory, args_offset, 0);
498 return Ok(self.set_expected_revert(
499 state,
500 ExpectedRevertData::Prefix(selector),
501 None,
502 1,
503 ));
504 }
505 if selector == selector!("expectPartialRevert(bytes4,address)") {
506 let selector = read_abi_bytes4_words_arg(&state.memory, args_offset, 0);
507 let reverter = read_abi_word_arg(&state.memory, args_offset, 1)?;
508 return Ok(self.set_expected_revert(
509 state,
510 ExpectedRevertData::Prefix(selector),
511 Some(reverter),
512 1,
513 ));
514 }
515 if selector == selector!("expectEmit()") {
516 return Ok(self.set_expected_emit(
517 state,
518 ExpectedEmitChecks::default_non_anonymous(),
519 None,
520 1,
521 ));
522 }
523 if selector == selector!("expectEmit(address)") {
524 let emitter = read_abi_word_arg(&state.memory, args_offset, 0)?;
525 return Ok(self.set_expected_emit(
526 state,
527 ExpectedEmitChecks::default_non_anonymous(),
528 Some(emitter),
529 1,
530 ));
531 }
532 if selector == selector!("expectEmit(uint64)") {
533 let count = read_abi_u64_arg(&state.memory, args_offset, 0, "symbolic vm.expectEmit")?;
534 return Ok(self.set_expected_emit(
535 state,
536 ExpectedEmitChecks::default_non_anonymous(),
537 None,
538 count,
539 ));
540 }
541 if selector == selector!("expectEmit(address,uint64)") {
542 let emitter = read_abi_word_arg(&state.memory, args_offset, 0)?;
543 let count = read_abi_u64_arg(&state.memory, args_offset, 1, "symbolic vm.expectEmit")?;
544 return Ok(self.set_expected_emit(
545 state,
546 ExpectedEmitChecks::default_non_anonymous(),
547 Some(emitter),
548 count,
549 ));
550 }
551 if selector == selector!("expectEmit(bool,bool,bool,bool)") {
552 let checks = ExpectedEmitChecks::from_non_anonymous_args(&state.memory, args_offset)?;
553 return Ok(self.set_expected_emit(state, checks, None, 1));
554 }
555 if selector == selector!("expectEmit(bool,bool,bool,bool,address)") {
556 let checks = ExpectedEmitChecks::from_non_anonymous_args(&state.memory, args_offset)?;
557 let emitter = read_abi_word_arg(&state.memory, args_offset, 4)?;
558 return Ok(self.set_expected_emit(state, checks, Some(emitter), 1));
559 }
560 if selector == selector!("expectEmit(bool,bool,bool,bool,uint64)") {
561 let checks = ExpectedEmitChecks::from_non_anonymous_args(&state.memory, args_offset)?;
562 let count = read_abi_u64_arg(&state.memory, args_offset, 4, "symbolic vm.expectEmit")?;
563 return Ok(self.set_expected_emit(state, checks, None, count));
564 }
565 if selector == selector!("expectEmit(bool,bool,bool,bool,address,uint64)") {
566 let checks = ExpectedEmitChecks::from_non_anonymous_args(&state.memory, args_offset)?;
567 let emitter = read_abi_word_arg(&state.memory, args_offset, 4)?;
568 let count = read_abi_u64_arg(&state.memory, args_offset, 5, "symbolic vm.expectEmit")?;
569 return Ok(self.set_expected_emit(state, checks, Some(emitter), count));
570 }
571 if selector == selector!("expectEmitAnonymous()") {
572 return Ok(self.set_expected_emit(
573 state,
574 ExpectedEmitChecks::default_anonymous(),
575 None,
576 1,
577 ));
578 }
579 if selector == selector!("expectEmitAnonymous(address)") {
580 let emitter = read_abi_word_arg(&state.memory, args_offset, 0)?;
581 return Ok(self.set_expected_emit(
582 state,
583 ExpectedEmitChecks::default_anonymous(),
584 Some(emitter),
585 1,
586 ));
587 }
588 if selector == selector!("expectEmitAnonymous(bool,bool,bool,bool,bool)") {
589 let checks = ExpectedEmitChecks::from_anonymous_args(&state.memory, args_offset)?;
590 return Ok(self.set_expected_emit(state, checks, None, 1));
591 }
592 if selector == selector!("expectEmitAnonymous(bool,bool,bool,bool,bool,address)") {
593 let checks = ExpectedEmitChecks::from_anonymous_args(&state.memory, args_offset)?;
594 let emitter = read_abi_word_arg(&state.memory, args_offset, 5)?;
595 return Ok(self.set_expected_emit(state, checks, Some(emitter), 1));
596 }
597 if selector == selector!("expectCall(address,bytes)") {
598 let callee = read_abi_word_arg(&state.memory, args_offset, 0)?;
599 let data = read_abi_symbolic_dynamic_bytes_arg(
600 state,
601 args_offset,
602 1,
603 self.config.max_calldata_bytes as usize,
604 "symbolic vm.expectCall",
605 )?;
606 return Ok(self.set_expected_call(state, callee, None, None, None, data, None));
607 }
608 if selector == selector!("expectCall(address,bytes,uint64)") {
609 let callee = read_abi_word_arg(&state.memory, args_offset, 0)?;
610 let data = read_abi_symbolic_dynamic_bytes_arg(
611 state,
612 args_offset,
613 1,
614 self.config.max_calldata_bytes as usize,
615 "symbolic vm.expectCall",
616 )?;
617 let count = read_abi_u64_arg(&state.memory, args_offset, 2, "symbolic vm.expectCall")?;
618 return Ok(self.set_expected_call(state, callee, None, None, None, data, Some(count)));
619 }
620 if selector == selector!("expectCall(address,uint256,bytes)") {
621 let callee = read_abi_word_arg(&state.memory, args_offset, 0)?;
622 let value = read_abi_concrete_word_arg(
623 &state.memory,
624 args_offset,
625 1,
626 "symbolic vm.expectCall",
627 )?;
628 let data = read_abi_symbolic_dynamic_bytes_arg(
629 state,
630 args_offset,
631 2,
632 self.config.max_calldata_bytes as usize,
633 "symbolic vm.expectCall",
634 )?;
635 return Ok(self.set_expected_call(state, callee, Some(value), None, None, data, None));
636 }
637 if selector == selector!("expectCall(address,uint256,bytes,uint64)") {
638 let callee = read_abi_word_arg(&state.memory, args_offset, 0)?;
639 let value = read_abi_concrete_word_arg(
640 &state.memory,
641 args_offset,
642 1,
643 "symbolic vm.expectCall",
644 )?;
645 let data = read_abi_symbolic_dynamic_bytes_arg(
646 state,
647 args_offset,
648 2,
649 self.config.max_calldata_bytes as usize,
650 "symbolic vm.expectCall",
651 )?;
652 let count = read_abi_u64_arg(&state.memory, args_offset, 3, "symbolic vm.expectCall")?;
653 return Ok(self.set_expected_call(
654 state,
655 callee,
656 Some(value),
657 None,
658 None,
659 data,
660 Some(count),
661 ));
662 }
663 if selector == selector!("expectCall(address,uint256,uint64,bytes)") {
664 let callee = read_abi_word_arg(&state.memory, args_offset, 0)?;
665 let value = read_abi_concrete_word_arg(
666 &state.memory,
667 args_offset,
668 1,
669 "symbolic vm.expectCall",
670 )?;
671 let gas = read_abi_u64_arg(&state.memory, args_offset, 2, "symbolic vm.expectCall")?;
672 let data = read_abi_symbolic_dynamic_bytes_arg(
673 state,
674 args_offset,
675 3,
676 self.config.max_calldata_bytes as usize,
677 "symbolic vm.expectCall",
678 )?;
679 return Ok(self.set_expected_call(
680 state,
681 callee,
682 Some(value),
683 Some(gas),
684 None,
685 data,
686 None,
687 ));
688 }
689 if selector == selector!("expectCall(address,uint256,uint64,bytes,uint64)") {
690 let callee = read_abi_word_arg(&state.memory, args_offset, 0)?;
691 let value = read_abi_concrete_word_arg(
692 &state.memory,
693 args_offset,
694 1,
695 "symbolic vm.expectCall",
696 )?;
697 let gas = read_abi_u64_arg(&state.memory, args_offset, 2, "symbolic vm.expectCall")?;
698 let data = read_abi_symbolic_dynamic_bytes_arg(
699 state,
700 args_offset,
701 3,
702 self.config.max_calldata_bytes as usize,
703 "symbolic vm.expectCall",
704 )?;
705 let count = read_abi_u64_arg(&state.memory, args_offset, 4, "symbolic vm.expectCall")?;
706 return Ok(self.set_expected_call(
707 state,
708 callee,
709 Some(value),
710 Some(gas),
711 None,
712 data,
713 Some(count),
714 ));
715 }
716 if selector == selector!("expectCallMinGas(address,uint256,uint64,bytes)") {
717 let callee = read_abi_word_arg(&state.memory, args_offset, 0)?;
718 let value = read_abi_concrete_word_arg(
719 &state.memory,
720 args_offset,
721 1,
722 "symbolic vm.expectCall",
723 )?;
724 let min_gas =
725 read_abi_u64_arg(&state.memory, args_offset, 2, "symbolic vm.expectCall")?;
726 let data = read_abi_symbolic_dynamic_bytes_arg(
727 state,
728 args_offset,
729 3,
730 self.config.max_calldata_bytes as usize,
731 "symbolic vm.expectCall",
732 )?;
733 return Ok(self.set_expected_call(
734 state,
735 callee,
736 Some(value),
737 None,
738 Some(min_gas),
739 data,
740 None,
741 ));
742 }
743 if selector == selector!("expectCallMinGas(address,uint256,uint64,bytes,uint64)") {
744 let callee = read_abi_word_arg(&state.memory, args_offset, 0)?;
745 let value = read_abi_concrete_word_arg(
746 &state.memory,
747 args_offset,
748 1,
749 "symbolic vm.expectCall",
750 )?;
751 let min_gas =
752 read_abi_u64_arg(&state.memory, args_offset, 2, "symbolic vm.expectCall")?;
753 let data = read_abi_symbolic_dynamic_bytes_arg(
754 state,
755 args_offset,
756 3,
757 self.config.max_calldata_bytes as usize,
758 "symbolic vm.expectCall",
759 )?;
760 let count = read_abi_u64_arg(&state.memory, args_offset, 4, "symbolic vm.expectCall")?;
761 return Ok(self.set_expected_call(
762 state,
763 callee,
764 Some(value),
765 None,
766 Some(min_gas),
767 data,
768 Some(count),
769 ));
770 }
771 if selector == selector!("expectCreate(bytes,address)")
772 || selector == selector!("expectCreate2(bytes,address)")
773 {
774 let bytecode = read_abi_dynamic_bytes_arg(
775 &state.memory,
776 args_offset,
777 0,
778 "symbolic vm.expectCreate bytecode",
779 )?;
780 let deployer = read_abi_word_arg(&state.memory, args_offset, 1)?;
781 let kind = if selector == selector!("expectCreate(bytes,address)") {
782 CreateKind::Create
783 } else {
784 CreateKind::Create2
785 };
786 return Ok(self.set_expected_create(state, bytecode, deployer, kind));
787 }
788 if selector == selector!("clearMockedCalls()") {
789 state.call_mocks.clear();
790 return Ok(CheatcodeOutcome::Continue(Vec::new()));
791 }
792 if selector == selector!("mockCall(address,bytes,bytes)") {
793 let callee = read_abi_word_arg(&state.memory, args_offset, 0)?;
794 let data = read_abi_symbolic_dynamic_bytes_arg(
795 state,
796 args_offset,
797 1,
798 self.config.max_calldata_bytes as usize,
799 "symbolic vm.mockCall",
800 )?;
801 let ret = read_abi_dynamic_return_data_arg(
802 state,
803 args_offset,
804 2,
805 self.config.max_calldata_bytes as usize,
806 "symbolic vm.mockCall",
807 )?;
808 return Ok(self.add_call_mock(state, callee, None, data, vec![ret], false));
809 }
810 if selector == selector!("mockCall(address,uint256,bytes,bytes)") {
811 let callee = read_abi_word_arg(&state.memory, args_offset, 0)?;
812 let value =
813 read_abi_concrete_word_arg(&state.memory, args_offset, 1, "symbolic vm.mockCall")?;
814 let data = read_abi_symbolic_dynamic_bytes_arg(
815 state,
816 args_offset,
817 2,
818 self.config.max_calldata_bytes as usize,
819 "symbolic vm.mockCall",
820 )?;
821 let ret = read_abi_dynamic_return_data_arg(
822 state,
823 args_offset,
824 3,
825 self.config.max_calldata_bytes as usize,
826 "symbolic vm.mockCall",
827 )?;
828 return Ok(self.add_call_mock(state, callee, Some(value), data, vec![ret], false));
829 }
830 if selector == selector!("mockCall(address,bytes4,bytes)") {
831 let callee = read_abi_word_arg(&state.memory, args_offset, 0)?;
832 let data = read_abi_bytes4_words_arg(&state.memory, args_offset, 1);
833 let ret = read_abi_dynamic_return_data_arg(
834 state,
835 args_offset,
836 2,
837 self.config.max_calldata_bytes as usize,
838 "symbolic vm.mockCall",
839 )?;
840 return Ok(self.add_call_mock(state, callee, None, data, vec![ret], false));
841 }
842 if selector == selector!("mockCall(address,uint256,bytes4,bytes)") {
843 let callee = read_abi_word_arg(&state.memory, args_offset, 0)?;
844 let value =
845 read_abi_concrete_word_arg(&state.memory, args_offset, 1, "symbolic vm.mockCall")?;
846 let data = read_abi_bytes4_words_arg(&state.memory, args_offset, 2);
847 let ret = read_abi_dynamic_return_data_arg(
848 state,
849 args_offset,
850 3,
851 self.config.max_calldata_bytes as usize,
852 "symbolic vm.mockCall",
853 )?;
854 return Ok(self.add_call_mock(state, callee, Some(value), data, vec![ret], false));
855 }
856 if selector == selector!("mockCalls(address,bytes,bytes[])")
857 || selector == selector!("mockCalls(address,uint256,bytes,bytes[])")
858 {
859 let has_value = selector == selector!("mockCalls(address,uint256,bytes,bytes[])");
860 let (value, data_idx, ret_idx) = if has_value {
861 let value = read_abi_concrete_word_arg(
862 &state.memory,
863 args_offset,
864 1,
865 "symbolic vm.mockCalls",
866 )?;
867 (Some(value), 2, 3)
868 } else {
869 (None, 1, 2)
870 };
871 let callee = read_abi_word_arg(&state.memory, args_offset, 0)?;
872 let data = read_abi_symbolic_dynamic_bytes_arg(
873 state,
874 args_offset,
875 data_idx,
876 self.config.max_calldata_bytes as usize,
877 "symbolic vm.mockCalls data",
878 )?;
879 let returns = read_abi_symbolic_dynamic_bytes_array_arg(
880 state,
881 args_offset,
882 ret_idx,
883 self.config.max_dynamic_length as usize,
884 self.config.max_calldata_bytes as usize,
885 )?;
886 return Ok(self.add_call_mock(state, callee, value, data, returns, false));
887 }
888 if selector == selector!("mockCallRevert(address,bytes,bytes)") {
889 let callee = read_abi_word_arg(&state.memory, args_offset, 0)?;
890 let data = read_abi_symbolic_dynamic_bytes_arg(
891 state,
892 args_offset,
893 1,
894 self.config.max_calldata_bytes as usize,
895 "symbolic vm.mockCallRevert",
896 )?;
897 let ret = read_abi_dynamic_return_data_arg(
898 state,
899 args_offset,
900 2,
901 self.config.max_calldata_bytes as usize,
902 "symbolic vm.mockCallRevert",
903 )?;
904 return Ok(self.add_call_mock(state, callee, None, data, vec![ret], true));
905 }
906 if selector == selector!("mockCallRevert(address,uint256,bytes,bytes)") {
907 let callee = read_abi_word_arg(&state.memory, args_offset, 0)?;
908 let value = read_abi_concrete_word_arg(
909 &state.memory,
910 args_offset,
911 1,
912 "symbolic vm.mockCallRevert",
913 )?;
914 let data = read_abi_symbolic_dynamic_bytes_arg(
915 state,
916 args_offset,
917 2,
918 self.config.max_calldata_bytes as usize,
919 "symbolic vm.mockCallRevert",
920 )?;
921 let ret = read_abi_dynamic_return_data_arg(
922 state,
923 args_offset,
924 3,
925 self.config.max_calldata_bytes as usize,
926 "symbolic vm.mockCallRevert",
927 )?;
928 return Ok(self.add_call_mock(state, callee, Some(value), data, vec![ret], true));
929 }
930 if selector == selector!("mockCallRevert(address,bytes4,bytes)") {
931 let callee = read_abi_word_arg(&state.memory, args_offset, 0)?;
932 let data = read_abi_bytes4_words_arg(&state.memory, args_offset, 1);
933 let ret = read_abi_dynamic_return_data_arg(
934 state,
935 args_offset,
936 2,
937 self.config.max_calldata_bytes as usize,
938 "symbolic vm.mockCallRevert",
939 )?;
940 return Ok(self.add_call_mock(state, callee, None, data, vec![ret], true));
941 }
942 if selector == selector!("mockCallRevert(address,uint256,bytes4,bytes)") {
943 let callee = read_abi_word_arg(&state.memory, args_offset, 0)?;
944 let value = read_abi_concrete_word_arg(
945 &state.memory,
946 args_offset,
947 1,
948 "symbolic vm.mockCallRevert",
949 )?;
950 let data = read_abi_bytes4_words_arg(&state.memory, args_offset, 2);
951 let ret = read_abi_dynamic_return_data_arg(
952 state,
953 args_offset,
954 3,
955 self.config.max_calldata_bytes as usize,
956 "symbolic vm.mockCallRevert",
957 )?;
958 return Ok(self.add_call_mock(state, callee, Some(value), data, vec![ret], true));
959 }
960 if selector == selector!("mockFunction(address,address,bytes)") {
961 let callee = read_abi_word_arg(&state.memory, args_offset, 0)?;
962 let target =
963 read_abi_address_arg(&state.memory, args_offset, 1, "symbolic vm.mockFunction")?;
964 let data = read_abi_symbolic_dynamic_bytes_arg(
965 state,
966 args_offset,
967 2,
968 self.config.max_calldata_bytes as usize,
969 "symbolic vm.mockFunction",
970 )?;
971 return Ok(self.set_function_mock(state, callee, target, data));
972 }
973 if selector == selector!("prank(address)") {
974 state.prank.next_caller =
975 Some(read_abi_address_word_or_symbolic_slot_arg(state, args_offset, 0)?);
976 state.prank.next_origin = None;
977 return Ok(CheatcodeOutcome::Continue(Vec::new()));
978 }
979 if selector == selector!("prank(address,address)") {
980 state.prank.next_caller =
981 Some(read_abi_address_word_or_symbolic_slot_arg(state, args_offset, 0)?);
982 state.prank.next_origin =
983 Some(read_abi_address_word_or_symbolic_slot_arg(state, args_offset, 1)?);
984 return Ok(CheatcodeOutcome::Continue(Vec::new()));
985 }
986 if selector == selector!("prank(address,bool)") {
987 let delegate_call =
988 read_abi_bool_arg(&state.memory, args_offset, 1, "symbolic vm.prank")?;
989 if delegate_call {
990 return Err(SymbolicError::Unsupported("symbolic vm.prank delegatecall"));
991 }
992 state.prank.next_caller =
993 Some(read_abi_address_word_or_symbolic_slot_arg(state, args_offset, 0)?);
994 state.prank.next_origin = None;
995 return Ok(CheatcodeOutcome::Continue(Vec::new()));
996 }
997 if selector == selector!("prank(address,address,bool)") {
998 let delegate_call =
999 read_abi_bool_arg(&state.memory, args_offset, 2, "symbolic vm.prank")?;
1000 if delegate_call {
1001 return Err(SymbolicError::Unsupported("symbolic vm.prank delegatecall"));
1002 }
1003 state.prank.next_caller =
1004 Some(read_abi_address_word_or_symbolic_slot_arg(state, args_offset, 0)?);
1005 state.prank.next_origin =
1006 Some(read_abi_address_word_or_symbolic_slot_arg(state, args_offset, 1)?);
1007 return Ok(CheatcodeOutcome::Continue(Vec::new()));
1008 }
1009 if selector == selector!("startPrank(address)") {
1010 state.prank.persistent_caller =
1011 Some(read_abi_address_word_or_symbolic_slot_arg(state, args_offset, 0)?);
1012 state.prank.persistent_origin = None;
1013 return Ok(CheatcodeOutcome::Continue(Vec::new()));
1014 }
1015 if selector == selector!("startPrank(address,address)") {
1016 state.prank.persistent_caller =
1017 Some(read_abi_address_word_or_symbolic_slot_arg(state, args_offset, 0)?);
1018 state.prank.persistent_origin =
1019 Some(read_abi_address_word_or_symbolic_slot_arg(state, args_offset, 1)?);
1020 return Ok(CheatcodeOutcome::Continue(Vec::new()));
1021 }
1022 if selector == selector!("startPrank(address,bool)") {
1023 let delegate_call =
1024 read_abi_bool_arg(&state.memory, args_offset, 1, "symbolic vm.startPrank")?;
1025 if delegate_call {
1026 return Err(SymbolicError::Unsupported("symbolic vm.startPrank delegatecall"));
1027 }
1028 state.prank.persistent_caller =
1029 Some(read_abi_address_word_or_symbolic_slot_arg(state, args_offset, 0)?);
1030 state.prank.persistent_origin = None;
1031 return Ok(CheatcodeOutcome::Continue(Vec::new()));
1032 }
1033 if selector == selector!("startPrank(address,address,bool)") {
1034 let delegate_call =
1035 read_abi_bool_arg(&state.memory, args_offset, 2, "symbolic vm.startPrank")?;
1036 if delegate_call {
1037 return Err(SymbolicError::Unsupported("symbolic vm.startPrank delegatecall"));
1038 }
1039 state.prank.persistent_caller =
1040 Some(read_abi_address_word_or_symbolic_slot_arg(state, args_offset, 0)?);
1041 state.prank.persistent_origin =
1042 Some(read_abi_address_word_or_symbolic_slot_arg(state, args_offset, 1)?);
1043 return Ok(CheatcodeOutcome::Continue(Vec::new()));
1044 }
1045 if selector == selector!("stopPrank()") {
1046 state.prank = SymbolicPrank::default();
1047 return Ok(CheatcodeOutcome::Continue(Vec::new()));
1048 }
1049 if selector == selector!("readCallers()") {
1050 return Ok(CheatcodeOutcome::Continue(state.read_callers_words()));
1051 }
1052 if selector == selector!("addr(uint256)") {
1053 let private_key =
1054 read_abi_constrained_word_arg(state, args_offset, 0, "symbolic vm.addr")?;
1055 let address = private_key_address(private_key)?;
1056 return Ok(CheatcodeOutcome::Continue(vec![SymWord::Concrete(address_word(address))]));
1057 }
1058 if selector == selector!("sign(uint256,bytes32)") {
1059 let private_key =
1060 read_abi_constrained_word_arg(state, args_offset, 0, "symbolic vm.sign")?;
1061 let digest = read_abi_constrained_word_arg(state, args_offset, 1, "symbolic vm.sign")?;
1062 return Ok(CheatcodeOutcome::Continue(sign_hash_words(private_key, digest)?));
1063 }
1064 if selector == selector!("signCompact(uint256,bytes32)") {
1065 let private_key =
1066 read_abi_constrained_word_arg(state, args_offset, 0, "symbolic vm.signCompact")?;
1067 let digest =
1068 read_abi_constrained_word_arg(state, args_offset, 1, "symbolic vm.signCompact")?;
1069 return Ok(CheatcodeOutcome::Continue(sign_compact_hash_words(private_key, digest)?));
1070 }
1071 if selector == selector!("deriveKey(string,uint32)") {
1072 let mnemonic =
1073 read_abi_string_arg(&state.memory, args_offset, 0, "symbolic vm.deriveKey")?;
1074 let index = read_abi_u32_arg(&state.memory, args_offset, 1, "symbolic vm.deriveKey")?;
1075 let private_key =
1076 derive_private_key::<English>(&mnemonic, DEFAULT_DERIVATION_PATH_PREFIX, index)?;
1077 return Ok(CheatcodeOutcome::Continue(vec![SymWord::Concrete(private_key)]));
1078 }
1079 if selector == selector!("deriveKey(string,string,uint32)") {
1080 let mnemonic =
1081 read_abi_string_arg(&state.memory, args_offset, 0, "symbolic vm.deriveKey")?;
1082 let path = read_abi_string_arg(&state.memory, args_offset, 1, "symbolic vm.deriveKey")?;
1083 let index = read_abi_u32_arg(&state.memory, args_offset, 2, "symbolic vm.deriveKey")?;
1084 let private_key = derive_private_key::<English>(&mnemonic, &path, index)?;
1085 return Ok(CheatcodeOutcome::Continue(vec![SymWord::Concrete(private_key)]));
1086 }
1087 if selector == selector!("deriveKey(string,uint32,string)") {
1088 let mnemonic =
1089 read_abi_string_arg(&state.memory, args_offset, 0, "symbolic vm.deriveKey")?;
1090 let index = read_abi_u32_arg(&state.memory, args_offset, 1, "symbolic vm.deriveKey")?;
1091 let language =
1092 read_abi_string_arg(&state.memory, args_offset, 2, "symbolic vm.deriveKey")?;
1093 let private_key = derive_private_key_with_language(
1094 &mnemonic,
1095 DEFAULT_DERIVATION_PATH_PREFIX,
1096 index,
1097 &language,
1098 )?;
1099 return Ok(CheatcodeOutcome::Continue(vec![SymWord::Concrete(private_key)]));
1100 }
1101 if selector == selector!("deriveKey(string,string,uint32,string)") {
1102 let mnemonic =
1103 read_abi_string_arg(&state.memory, args_offset, 0, "symbolic vm.deriveKey")?;
1104 let path = read_abi_string_arg(&state.memory, args_offset, 1, "symbolic vm.deriveKey")?;
1105 let index = read_abi_u32_arg(&state.memory, args_offset, 2, "symbolic vm.deriveKey")?;
1106 let language =
1107 read_abi_string_arg(&state.memory, args_offset, 3, "symbolic vm.deriveKey")?;
1108 let private_key = derive_private_key_with_language(&mnemonic, &path, index, &language)?;
1109 return Ok(CheatcodeOutcome::Continue(vec![SymWord::Concrete(private_key)]));
1110 }
1111 if selector == selector!("rememberKey(uint256)") {
1112 let private_key =
1113 read_abi_constrained_word_arg(state, args_offset, 0, "symbolic vm.rememberKey")?;
1114 let address = private_key_address(private_key)?;
1115 state.wallets.insert(address);
1116 return Ok(CheatcodeOutcome::Continue(vec![SymWord::Concrete(address_word(address))]));
1117 }
1118 if selector == selector!("rememberKeys(string,string,uint32)")
1119 || selector == selector!("rememberKeys(string,string,string,uint32)")
1120 {
1121 let mnemonic =
1122 read_abi_string_arg(&state.memory, args_offset, 0, "symbolic vm.rememberKeys")?;
1123 let path =
1124 read_abi_string_arg(&state.memory, args_offset, 1, "symbolic vm.rememberKeys")?;
1125 let (language, count_index) =
1126 if selector == selector!("rememberKeys(string,string,string,uint32)") {
1127 (
1128 Some(read_abi_string_arg(
1129 &state.memory,
1130 args_offset,
1131 2,
1132 "symbolic vm.rememberKeys",
1133 )?),
1134 3,
1135 )
1136 } else {
1137 (None, 2)
1138 };
1139 let count = read_abi_u32_arg(
1140 &state.memory,
1141 args_offset,
1142 count_index,
1143 "symbolic vm.rememberKeys",
1144 )?;
1145 if count > MAX_REMEMBER_KEYS {
1146 return Err(SymbolicError::Unsupported("symbolic vm.rememberKeys count"));
1147 }
1148 let mut addresses = Vec::with_capacity(count as usize);
1149 for index in 0..count {
1150 let private_key = if let Some(language) = &language {
1151 derive_private_key_with_language(&mnemonic, &path, index, language)?
1152 } else {
1153 derive_private_key::<English>(&mnemonic, &path, index)?
1154 };
1155 let address = private_key_address(private_key)?;
1156 state.wallets.insert(address);
1157 addresses.push(DynSolValue::Address(address));
1158 }
1159 return Ok(CheatcodeOutcome::ContinueData(abi_concrete_value_return(
1160 DynSolValue::Array(addresses),
1161 )));
1162 }
1163 if selector == selector!("getWallets()") {
1164 let wallets = DynSolValue::Array(
1165 state.wallets.iter().copied().map(DynSolValue::Address).collect(),
1166 );
1167 return Ok(CheatcodeOutcome::ContinueData(abi_concrete_value_return(wallets)));
1168 }
1169 if selector == selector!("store(address,bytes32,bytes32)") {
1170 let target = read_abi_address_or_symbolic_slot_arg(state, args_offset, 0)?;
1171 let slot = state.memory.load_word(in_offset + 36)?;
1172 let value = state.memory.load_word(in_offset + 68)?;
1173 if target == CHEATCODE_ADDRESS
1174 && slot == SymWord::Concrete(failed_slot())
1175 && value == SymWord::Concrete(U256::from(1))
1176 {
1177 return Ok(CheatcodeOutcome::Failure);
1178 }
1179 state.world.sstore(target, slot, value);
1180 return Ok(CheatcodeOutcome::Continue(Vec::new()));
1181 }
1182 if selector == selector!("load(address,bytes32)") {
1183 let target = read_abi_address_or_symbolic_slot_arg(state, args_offset, 0)?;
1184 let slot = state.memory.load_word(in_offset + 36)?;
1185 let concrete_slot = state.constrained_word(&slot);
1186 let value = state.world.sload(executor, target, slot, concrete_slot)?;
1187 return Ok(CheatcodeOutcome::Continue(vec![value]));
1188 }
1189 if selector == selector!("getNonce(address)") {
1190 let target = read_abi_address_or_symbolic_slot_arg(state, args_offset, 0)?;
1191 let nonce = state.world.nonce(executor, target)?;
1192 return Ok(CheatcodeOutcome::Continue(vec![SymWord::Concrete(U256::from(nonce))]));
1193 }
1194 if selector == selector!("computeCreateAddress(address,uint256)") {
1195 let deployer = read_abi_word_arg(&state.memory, args_offset, 0)?;
1196 let nonce = read_abi_word_arg(&state.memory, args_offset, 1)?;
1197 let address = compute_create_address_word(state, deployer, nonce)?;
1198 return Ok(CheatcodeOutcome::Continue(vec![address]));
1199 }
1200 if selector == selector!("computeCreate2Address(bytes32,bytes32,address)") {
1201 let salt = read_abi_word_arg(&state.memory, args_offset, 0)?;
1202 let init_code_hash = read_abi_word_arg(&state.memory, args_offset, 1)?;
1203 let deployer = read_abi_word_arg(&state.memory, args_offset, 2)?;
1204 let address = compute_create2_address_word(state, deployer, salt, init_code_hash)?;
1205 return Ok(CheatcodeOutcome::Continue(vec![address]));
1206 }
1207 if selector == selector!("computeCreate2Address(bytes32,bytes32)") {
1208 let salt = read_abi_word_arg(&state.memory, args_offset, 0)?;
1209 let init_code_hash = read_abi_word_arg(&state.memory, args_offset, 1)?;
1210 let address = compute_create2_address_word(
1211 state,
1212 SymWord::Concrete(address_word(DEFAULT_CREATE2_DEPLOYER)),
1213 salt,
1214 init_code_hash,
1215 )?;
1216 return Ok(CheatcodeOutcome::Continue(vec![address]));
1217 }
1218 if selector == selector!("etch(address,bytes)") {
1219 let target = read_abi_address_or_symbolic_slot_arg(state, args_offset, 0)?;
1220 let code = read_abi_symbolic_dynamic_bytes_arg(
1221 state,
1222 args_offset,
1223 1,
1224 self.config.max_dynamic_length as usize,
1225 "symbolic vm.etch",
1226 )?;
1227 state.world.install_code(target, SymCode { bytes: code });
1228 return Ok(CheatcodeOutcome::Continue(Vec::new()));
1229 }
1230 if selector == selector!("getCode(string)")
1231 || selector == selector!("getDeployedCode(string)")
1232 {
1233 let artifact =
1234 read_abi_string_arg(&state.memory, args_offset, 0, "symbolic vm.getCode")?;
1235 let code = artifact_code(&artifact, selector == selector!("getDeployedCode(string)"))?;
1236 return Ok(CheatcodeOutcome::ContinueData(abi_concrete_bytes_return(code)));
1237 }
1238 if selector == selector!("deal(address,uint256)") {
1239 let target = read_abi_address_or_symbolic_slot_arg(state, args_offset, 0)?;
1240 let value = read_abi_word_arg(&state.memory, args_offset, 1)?;
1241 if value.contains_gasleft() {
1242 return Err(SymbolicError::Unsupported("GAS/gasleft() not modeled"));
1243 }
1244 let value = state.constrained_word(&value).map(SymWord::Concrete).unwrap_or(value);
1245 state.world.set_balance_word(target, value);
1246 return Ok(CheatcodeOutcome::Continue(Vec::new()));
1247 }
1248 if selector == selector!("setNonce(address,uint64)")
1249 || selector == selector!("setNonceUnsafe(address,uint64)")
1250 {
1251 let target = read_abi_address_or_symbolic_slot_arg(state, args_offset, 0)?;
1252 let nonce =
1253 read_abi_constrained_word_arg(state, args_offset, 1, "symbolic vm.setNonce")?;
1254 if nonce > U256::from(u64::MAX) {
1255 return Err(SymbolicError::Unsupported("symbolic vm.setNonce nonce"));
1256 }
1257 let nonce = nonce.to::<u64>();
1258 if selector == selector!("setNonce(address,uint64)")
1259 && nonce < state.world.nonce(executor, target)?
1260 {
1261 return Ok(CheatcodeOutcome::Failure);
1262 }
1263 state.world.set_nonce(target, nonce);
1264 return Ok(CheatcodeOutcome::Continue(Vec::new()));
1265 }
1266 if selector == selector!("resetNonce(address)") {
1267 let target = read_abi_address_or_symbolic_slot_arg(state, args_offset, 0)?;
1268 let nonce = if state.world.extcode(executor, target)?.is_empty() { 0 } else { 1 };
1269 state.world.set_nonce(target, nonce);
1270 return Ok(CheatcodeOutcome::Continue(Vec::new()));
1271 }
1272 if selector == selector!("allowCheatcodes(address)") {
1273 return Ok(CheatcodeOutcome::Continue(Vec::new()));
1274 }
1275 if selector == selector!("makePersistent(address)") {
1276 let account = read_abi_address_or_symbolic_slot_arg(state, args_offset, 0)?;
1277 state.persistent_accounts.insert(account);
1278 return Ok(CheatcodeOutcome::Continue(Vec::new()));
1279 }
1280 if selector == selector!("makePersistent(address,address)") {
1281 let account0 = read_abi_address_or_symbolic_slot_arg(state, args_offset, 0)?;
1282 let account1 = read_abi_address_or_symbolic_slot_arg(state, args_offset, 1)?;
1283 state.persistent_accounts.insert(account0);
1284 state.persistent_accounts.insert(account1);
1285 return Ok(CheatcodeOutcome::Continue(Vec::new()));
1286 }
1287 if selector == selector!("makePersistent(address,address,address)") {
1288 let account0 = read_abi_address_or_symbolic_slot_arg(state, args_offset, 0)?;
1289 let account1 = read_abi_address_or_symbolic_slot_arg(state, args_offset, 1)?;
1290 let account2 = read_abi_address_or_symbolic_slot_arg(state, args_offset, 2)?;
1291 state.persistent_accounts.insert(account0);
1292 state.persistent_accounts.insert(account1);
1293 state.persistent_accounts.insert(account2);
1294 return Ok(CheatcodeOutcome::Continue(Vec::new()));
1295 }
1296 if selector == selector!("makePersistent(address[])") {
1297 let values = decode_cheatcode_args(
1298 state,
1299 in_offset,
1300 in_size,
1301 vec![DynSolType::Array(Box::new(DynSolType::Address))],
1302 )?;
1303 for account in dyn_address_array(&values[0])? {
1304 state.persistent_accounts.insert(account);
1305 }
1306 return Ok(CheatcodeOutcome::Continue(Vec::new()));
1307 }
1308 if selector == selector!("revokePersistent(address)") {
1309 let account = read_abi_address_or_symbolic_slot_arg(state, args_offset, 0)?;
1310 state.persistent_accounts.remove(&account);
1311 return Ok(CheatcodeOutcome::Continue(Vec::new()));
1312 }
1313 if selector == selector!("revokePersistent(address[])") {
1314 let values = decode_cheatcode_args(
1315 state,
1316 in_offset,
1317 in_size,
1318 vec![DynSolType::Array(Box::new(DynSolType::Address))],
1319 )?;
1320 for account in dyn_address_array(&values[0])? {
1321 state.persistent_accounts.remove(&account);
1322 }
1323 return Ok(CheatcodeOutcome::Continue(Vec::new()));
1324 }
1325 if selector == selector!("isPersistent(address)") {
1326 let account = read_abi_address_or_symbolic_slot_arg(state, args_offset, 0)?;
1327 return Ok(CheatcodeOutcome::Continue(vec![SymWord::Concrete(U256::from(
1328 state.persistent_accounts.contains(&account),
1329 ))]));
1330 }
1331 if selector == selector!("activeFork()") {
1332 let id = executor.backend().active_fork_id().ok_or(SymbolicError::Unsupported(
1333 "symbolic vm.activeFork requires an active forked executor",
1334 ))?;
1335 return Ok(CheatcodeOutcome::Continue(vec![SymWord::Concrete(id)]));
1336 }
1337 if selector == selector!("selectFork(uint256)") {
1338 let id =
1339 read_abi_constrained_word_arg(state, args_offset, 0, "symbolic vm.selectFork id")?;
1340 if executor.backend().is_active_fork(id) {
1341 return Ok(CheatcodeOutcome::Continue(Vec::new()));
1342 }
1343 return Err(SymbolicError::Unsupported(
1344 "symbolic vm.selectFork can only select the already active fork",
1345 ));
1346 }
1347 if selector == selector!("rollFork(uint256)") {
1348 let block_number = read_abi_constrained_word_arg(
1349 state,
1350 args_offset,
1351 0,
1352 "symbolic vm.rollFork block number",
1353 )?;
1354 let current =
1355 state.block.number.clone().into_concrete("symbolic vm.rollFork current block")?;
1356 if block_number == current {
1357 return Ok(CheatcodeOutcome::Continue(Vec::new()));
1358 }
1359 return Err(SymbolicError::Unsupported(
1360 "symbolic vm.rollFork cannot change the active fork block during symbolic execution",
1361 ));
1362 }
1363 if selector == selector!("rollFork(uint256,uint256)") {
1364 let id =
1365 read_abi_constrained_word_arg(state, args_offset, 0, "symbolic vm.rollFork id")?;
1366 let block_number = read_abi_constrained_word_arg(
1367 state,
1368 args_offset,
1369 1,
1370 "symbolic vm.rollFork block number",
1371 )?;
1372 let current =
1373 state.block.number.clone().into_concrete("symbolic vm.rollFork current block")?;
1374 if executor.backend().is_active_fork(id) && block_number == current {
1375 return Ok(CheatcodeOutcome::Continue(Vec::new()));
1376 }
1377 return Err(SymbolicError::Unsupported(
1378 "symbolic vm.rollFork cannot change the active fork block during symbolic execution",
1379 ));
1380 }
1381 if selector == selector!("createFork(string)")
1382 || selector == selector!("createFork(string,uint256)")
1383 || selector == selector!("createFork(string,bytes32)")
1384 || selector == selector!("createSelectFork(string)")
1385 || selector == selector!("createSelectFork(string,uint256)")
1386 || selector == selector!("createSelectFork(string,bytes32)")
1387 || selector == selector!("rollFork(bytes32)")
1388 || selector == selector!("rollFork(uint256,bytes32)")
1389 {
1390 return Err(SymbolicError::Unsupported(
1391 "symbolic fork creation and fork block mutation must happen before symbolic execution",
1392 ));
1393 }
1394 if selector == selector!("snapshot()") || selector == selector!("snapshotState()") {
1395 let id = state.world.snapshot_state();
1396 return Ok(CheatcodeOutcome::Continue(vec![SymWord::Concrete(id)]));
1397 }
1398 if selector == selector!("revertTo(uint256)")
1399 || selector == selector!("revertToState(uint256)")
1400 || selector == selector!("revertToAndDelete(uint256)")
1401 || selector == selector!("revertToStateAndDelete(uint256)")
1402 {
1403 let id = read_abi_constrained_word_arg(
1404 state,
1405 args_offset,
1406 0,
1407 "symbolic vm.revertToState snapshot",
1408 )?;
1409 let success = state.world.restore_snapshot(id);
1410 if success
1411 && (selector == selector!("revertToAndDelete(uint256)")
1412 || selector == selector!("revertToStateAndDelete(uint256)"))
1413 {
1414 state.world.delete_snapshot(id);
1415 }
1416 return Ok(CheatcodeOutcome::Continue(vec![SymWord::Concrete(U256::from(success))]));
1417 }
1418 if selector == selector!("deleteSnapshot(uint256)")
1419 || selector == selector!("deleteStateSnapshot(uint256)")
1420 {
1421 let id = read_abi_constrained_word_arg(
1422 state,
1423 args_offset,
1424 0,
1425 "symbolic vm.deleteStateSnapshot snapshot",
1426 )?;
1427 let success = state.world.delete_snapshot(id);
1428 return Ok(CheatcodeOutcome::Continue(vec![SymWord::Concrete(U256::from(success))]));
1429 }
1430 if selector == selector!("deleteSnapshots()")
1431 || selector == selector!("deleteStateSnapshots()")
1432 {
1433 state.world.delete_snapshots();
1434 return Ok(CheatcodeOutcome::Continue(Vec::new()));
1435 }
1436 if selector == selector!("warp(uint256)") {
1437 state.block.timestamp = state.memory.load_word(in_offset + 4)?;
1438 return Ok(CheatcodeOutcome::Continue(Vec::new()));
1439 }
1440 if selector == selector!("roll(uint256)") {
1441 state.block.number = state.memory.load_word(in_offset + 4)?;
1442 return Ok(CheatcodeOutcome::Continue(Vec::new()));
1443 }
1444 if selector == selector!("setBlockhash(uint256,bytes32)") {
1445 let block_number = read_abi_constrained_word_arg(
1446 state,
1447 args_offset,
1448 0,
1449 "symbolic vm.setBlockhash block number",
1450 )?;
1451 let block_hash = state.memory.load_word(in_offset + 36)?;
1452 state.block.set_block_hash(block_number, block_hash)?;
1453 return Ok(CheatcodeOutcome::Continue(Vec::new()));
1454 }
1455 if selector == selector!("prevrandao(bytes32)")
1456 || selector == selector!("prevrandao(uint256)")
1457 {
1458 state.block.difficulty = state.memory.load_word(in_offset + 4)?;
1459 return Ok(CheatcodeOutcome::Continue(Vec::new()));
1460 }
1461 if selector == selector!("blobhashes(bytes32[])") {
1462 let values = decode_cheatcode_args(
1463 state,
1464 in_offset,
1465 in_size,
1466 vec![DynSolType::Array(Box::new(DynSolType::FixedBytes(32)))],
1467 )?;
1468 state.block.set_blob_hashes(dyn_bytes32_array(&values[0])?);
1469 return Ok(CheatcodeOutcome::Continue(Vec::new()));
1470 }
1471 if selector == selector!("getBlobhashes()") {
1472 let value = DynSolValue::Array(
1473 state
1474 .block
1475 .blob_hashes
1476 .iter()
1477 .copied()
1478 .map(|hash| DynSolValue::FixedBytes(hash, 32))
1479 .collect(),
1480 );
1481 return Ok(CheatcodeOutcome::ContinueData(abi_concrete_value_return(value)));
1482 }
1483 if selector == selector!("fee(uint256)") {
1484 state.block.basefee = state.memory.load_word(in_offset + 4)?;
1485 return Ok(CheatcodeOutcome::Continue(Vec::new()));
1486 }
1487 if selector == selector!("blobBaseFee(uint256)") {
1488 state.block.blob_basefee = state.memory.load_word(in_offset + 4)?;
1489 return Ok(CheatcodeOutcome::Continue(Vec::new()));
1490 }
1491 if selector == selector!("getBlobBaseFee()") {
1492 return Ok(CheatcodeOutcome::Continue(vec![state.block.blob_basefee.clone()]));
1493 }
1494 if selector == selector!("chainId(uint256)") {
1495 state.block.chain_id = state.memory.load_word(in_offset + 4)?;
1496 return Ok(CheatcodeOutcome::Continue(Vec::new()));
1497 }
1498 if selector == selector!("getChainId()") {
1499 return Ok(CheatcodeOutcome::Continue(vec![state.block.chain_id.clone()]));
1500 }
1501 if selector == selector!("difficulty(uint256)") {
1502 state.block.difficulty = state.memory.load_word(in_offset + 4)?;
1503 return Ok(CheatcodeOutcome::Continue(Vec::new()));
1504 }
1505 if selector == selector!("coinbase(address)") {
1506 let coinbase = read_abi_constrained_address_arg(
1507 state,
1508 args_offset,
1509 0,
1510 "symbolic vm.coinbase value",
1511 )?;
1512 state.block.coinbase = coinbase;
1513 return Ok(CheatcodeOutcome::Continue(Vec::new()));
1514 }
1515 if selector == selector!("getBlockNumber()") {
1516 return Ok(CheatcodeOutcome::Continue(vec![state.block.number.clone()]));
1517 }
1518 if selector == selector!("txGasPrice(uint256)") {
1519 state.gas_price = state.memory.load_word(in_offset + 4)?;
1520 return Ok(CheatcodeOutcome::Continue(Vec::new()));
1521 }
1522 if selector == selector!("getBlockTimestamp()") {
1523 return Ok(CheatcodeOutcome::Continue(vec![state.block.timestamp.clone()]));
1524 }
1525 if selector == selector!("label(address,string)") {
1526 let values = decode_cheatcode_args(
1527 state,
1528 in_offset,
1529 in_size,
1530 vec![DynSolType::Address, DynSolType::String],
1531 )?;
1532 let account = dyn_address(&values[0])?;
1533 let label = dyn_string(&values[1])?;
1534 state.labels.insert(account, label);
1535 return Ok(CheatcodeOutcome::Continue(Vec::new()));
1536 }
1537 if selector == selector!("getLabel(address)") {
1538 let account =
1539 read_abi_address_arg(&state.memory, args_offset, 0, "symbolic vm.getLabel")?;
1540 let label = state
1541 .labels
1542 .get(&account)
1543 .cloned()
1544 .unwrap_or_else(|| format!("unlabeled:{account}"));
1545 return Ok(CheatcodeOutcome::ContinueData(abi_concrete_bytes_return(label.bytes())));
1546 }
1547 if selector == selector!("expectSafeMemory(uint64,uint64)") {
1548 return Err(SymbolicError::Unsupported("symbolic vm.expectSafeMemory not modeled"));
1549 }
1550 if selector == selector!("expectSafeMemoryCall(uint64,uint64)") {
1551 return Err(SymbolicError::Unsupported("symbolic vm.expectSafeMemoryCall not modeled"));
1552 }
1553 if selector == selector!("stopExpectSafeMemory()") {
1554 return Err(SymbolicError::Unsupported("symbolic vm.stopExpectSafeMemory not modeled"));
1555 }
1556 if selector == selector!("lastCallGas()") {
1557 return Err(SymbolicError::Unsupported("symbolic vm.lastCallGas not modeled"));
1558 }
1559 if selector == selector!("snapshotGasLastCall(string)")
1560 || selector == selector!("snapshotGasLastCall(string,string)")
1561 {
1562 return Err(SymbolicError::Unsupported("symbolic vm.snapshotGasLastCall not modeled"));
1563 }
1564 if selector == selector!("stopSnapshotGas()")
1565 || selector == selector!("stopSnapshotGas(string)")
1566 || selector == selector!("stopSnapshotGas(string,string)")
1567 {
1568 return Err(SymbolicError::Unsupported("symbolic vm.stopSnapshotGas not modeled"));
1569 }
1570 if selector == selector!("pauseGasMetering()")
1571 || selector == selector!("resumeGasMetering()")
1572 || selector == selector!("resetGasMetering()")
1573 || selector == selector!("breakpoint(string)")
1574 || selector == selector!("breakpoint(string,bool)")
1575 || selector == selector!("snapshotValue(string,uint256)")
1576 || selector == selector!("snapshotValue(string,string,uint256)")
1577 || selector == selector!("startSnapshotGas(string)")
1578 || selector == selector!("startSnapshotGas(string,string)")
1579 || selector == selector!("sleep(uint256)")
1580 || selector == selector!("cool(address)")
1581 || selector == selector!("accessList((address,bytes32[])[])")
1582 || selector == selector!("warmSlot(address,bytes32)")
1583 || selector == selector!("coolSlot(address,bytes32)")
1584 || selector == selector!("noAccessList()")
1585 {
1586 return Ok(CheatcodeOutcome::Continue(Vec::new()));
1587 }
1588 if selector == selector!("setEvmVersion(string)") {
1589 return Err(SymbolicError::Unsupported("symbolic vm.setEvmVersion not modeled"));
1590 }
1591 if selector == selector!("getEvmVersion()") {
1592 return Err(SymbolicError::Unsupported("symbolic vm.getEvmVersion not modeled"));
1593 }
1594 if selector == selector!("getFoundryVersion()") {
1595 return Ok(CheatcodeOutcome::ContinueData(abi_concrete_bytes_return(
1596 env!("CARGO_PKG_VERSION").bytes(),
1597 )));
1598 }
1599 if selector == selector!("projectRoot()") {
1600 let root = std::env::current_dir()
1601 .map_err(|_| SymbolicError::Unsupported("symbolic vm.projectRoot"))?;
1602 return Ok(CheatcodeOutcome::ContinueData(abi_concrete_bytes_return(
1603 root.display().to_string().bytes(),
1604 )));
1605 }
1606 if selector == selector!("unixTime()") {
1607 let milliseconds = SystemTime::now()
1608 .duration_since(UNIX_EPOCH)
1609 .map_err(|_| SymbolicError::Unsupported("symbolic vm.unixTime"))?
1610 .as_millis();
1611 let value = U256::try_from(milliseconds)
1612 .map_err(|_| SymbolicError::Unsupported("symbolic vm.unixTime"))?;
1613 return Ok(CheatcodeOutcome::Continue(vec![SymWord::Concrete(value)]));
1614 }
1615 if selector == selector!("isContext(uint8)") {
1616 let context =
1617 read_abi_concrete_word_arg(&state.memory, args_offset, 0, "symbolic vm.isContext")?;
1618 return Ok(CheatcodeOutcome::Continue(vec![SymWord::Concrete(U256::from(
1619 context == U256::ZERO || context == U256::from(1),
1620 ))]));
1621 }
1622 if selector == selector!("toString(address)") {
1623 let address =
1624 read_abi_address_arg(&state.memory, args_offset, 0, "symbolic vm.toString")?;
1625 return Ok(CheatcodeOutcome::ContinueData(abi_concrete_bytes_return(
1626 format!("{address:?}").bytes(),
1627 )));
1628 }
1629 if selector == selector!("toString(bytes)") {
1630 let bytes =
1631 read_abi_dynamic_bytes_arg(&state.memory, args_offset, 0, "symbolic vm.toString")?;
1632 return Ok(CheatcodeOutcome::ContinueData(abi_concrete_bytes_return(
1633 format!("0x{}", hex::encode(bytes)).bytes(),
1634 )));
1635 }
1636 if selector == selector!("toString(bytes32)") {
1637 let value =
1638 read_abi_concrete_word_arg(&state.memory, args_offset, 0, "symbolic vm.toString")?;
1639 return Ok(CheatcodeOutcome::ContinueData(abi_concrete_bytes_return(
1640 format!("0x{}", hex::encode(value.to_be_bytes::<32>())).bytes(),
1641 )));
1642 }
1643 if selector == selector!("toString(bool)") {
1644 let value = read_abi_bool_arg(&state.memory, args_offset, 0, "symbolic vm.toString")?;
1645 return Ok(CheatcodeOutcome::ContinueData(abi_concrete_bytes_return(
1646 if value { "true" } else { "false" }.bytes(),
1647 )));
1648 }
1649 if selector == selector!("toString(uint256)") {
1650 let value =
1651 read_abi_concrete_word_arg(&state.memory, args_offset, 0, "symbolic vm.toString")?;
1652 return Ok(CheatcodeOutcome::ContinueData(abi_concrete_bytes_return(
1653 value.to_string().bytes(),
1654 )));
1655 }
1656 if selector == selector!("toString(int256)") {
1657 let value =
1658 read_abi_concrete_word_arg(&state.memory, args_offset, 0, "symbolic vm.toString")?;
1659 return Ok(CheatcodeOutcome::ContinueData(abi_concrete_bytes_return(
1660 I256::from_raw(value).to_string().bytes(),
1661 )));
1662 }
1663 if selector == selector!("parseBytes(string)") {
1664 let value =
1665 read_abi_string_arg(&state.memory, args_offset, 0, "symbolic vm.parseBytes")?;
1666 return Ok(CheatcodeOutcome::ContinueData(abi_concrete_bytes_return(parse_env_bytes(
1667 &value,
1668 )?)));
1669 }
1670 if selector == selector!("parseAddress(string)") {
1671 let value =
1672 read_abi_string_arg(&state.memory, args_offset, 0, "symbolic vm.parseAddress")?;
1673 return Ok(CheatcodeOutcome::Continue(vec![SymWord::Concrete(address_word(
1674 parse_env_address(&value)?,
1675 ))]));
1676 }
1677 if selector == selector!("parseUint(string)") {
1678 let value =
1679 read_abi_string_arg(&state.memory, args_offset, 0, "symbolic vm.parseUint")?;
1680 return Ok(CheatcodeOutcome::Continue(vec![SymWord::Concrete(parse_env_uint(
1681 &value,
1682 )?)]));
1683 }
1684 if selector == selector!("parseInt(string)") {
1685 let value = read_abi_string_arg(&state.memory, args_offset, 0, "symbolic vm.parseInt")?;
1686 return Ok(CheatcodeOutcome::Continue(vec![SymWord::Concrete(parse_env_int(&value)?)]));
1687 }
1688 if selector == selector!("parseBytes32(string)") {
1689 let value =
1690 read_abi_string_arg(&state.memory, args_offset, 0, "symbolic vm.parseBytes32")?;
1691 return Ok(CheatcodeOutcome::Continue(vec![SymWord::Concrete(parse_env_bytes32(
1692 &value,
1693 )?)]));
1694 }
1695 if selector == selector!("parseBool(string)") {
1696 let value =
1697 read_abi_string_arg(&state.memory, args_offset, 0, "symbolic vm.parseBool")?;
1698 return Ok(CheatcodeOutcome::Continue(vec![SymWord::Concrete(U256::from(
1699 parse_env_bool(&value)?,
1700 ))]));
1701 }
1702 if selector == selector!("toLowercase(string)")
1703 || selector == selector!("toUppercase(string)")
1704 || selector == selector!("trim(string)")
1705 {
1706 let value = read_abi_string_arg(&state.memory, args_offset, 0, "symbolic vm.string")?;
1707 let output = if selector == selector!("toLowercase(string)") {
1708 value.to_lowercase()
1709 } else if selector == selector!("toUppercase(string)") {
1710 value.to_uppercase()
1711 } else {
1712 value.trim().to_string()
1713 };
1714 return Ok(CheatcodeOutcome::ContinueData(abi_concrete_bytes_return(output.bytes())));
1715 }
1716 if selector == selector!("replace(string,string,string)") {
1717 let values = decode_cheatcode_args(
1718 state,
1719 in_offset,
1720 in_size,
1721 vec![DynSolType::String, DynSolType::String, DynSolType::String],
1722 )?;
1723 let output =
1724 dyn_string(&values[0])?.replace(&dyn_string(&values[1])?, &dyn_string(&values[2])?);
1725 return Ok(CheatcodeOutcome::ContinueData(abi_concrete_bytes_return(output.bytes())));
1726 }
1727 if selector == selector!("split(string,string)") {
1728 let values = decode_cheatcode_args(
1729 state,
1730 in_offset,
1731 in_size,
1732 vec![DynSolType::String, DynSolType::String],
1733 )?;
1734 let input = dyn_string(&values[0])?;
1735 let delimiter = dyn_string(&values[1])?;
1736 let parts = if delimiter.is_empty() {
1737 input.chars().map(|ch| DynSolValue::String(ch.to_string())).collect()
1738 } else {
1739 input.split(&delimiter).map(|part| DynSolValue::String(part.to_string())).collect()
1740 };
1741 return Ok(CheatcodeOutcome::ContinueData(abi_concrete_value_return(
1742 DynSolValue::Array(parts),
1743 )));
1744 }
1745 if selector == selector!("indexOf(string,string)") {
1746 let values = decode_cheatcode_args(
1747 state,
1748 in_offset,
1749 in_size,
1750 vec![DynSolType::String, DynSolType::String],
1751 )?;
1752 let input = dyn_string(&values[0])?;
1753 let needle = dyn_string(&values[1])?;
1754 let index = input.find(&needle).map(U256::from).unwrap_or(U256::MAX);
1755 return Ok(CheatcodeOutcome::Continue(vec![SymWord::Concrete(index)]));
1756 }
1757 if selector == selector!("contains(string,string)") {
1758 let values = decode_cheatcode_args(
1759 state,
1760 in_offset,
1761 in_size,
1762 vec![DynSolType::String, DynSolType::String],
1763 )?;
1764 let contains = dyn_string(&values[0])?.contains(&dyn_string(&values[1])?);
1765 return Ok(CheatcodeOutcome::Continue(vec![SymWord::Concrete(U256::from(contains))]));
1766 }
1767 if selector == selector!("toBase64(bytes)")
1768 || selector == selector!("toBase64(string)")
1769 || selector == selector!("toBase64URL(bytes)")
1770 || selector == selector!("toBase64URL(string)")
1771 {
1772 let data =
1773 read_abi_dynamic_bytes_arg(&state.memory, args_offset, 0, "symbolic vm.toBase64")?;
1774 let encoded = if selector == selector!("toBase64URL(bytes)")
1775 || selector == selector!("toBase64URL(string)")
1776 {
1777 BASE64_URL_SAFE.encode(data)
1778 } else {
1779 BASE64_STANDARD.encode(data)
1780 };
1781 return Ok(CheatcodeOutcome::ContinueData(abi_concrete_bytes_return(encoded.bytes())));
1782 }
1783 if selector == selector!("bound(uint256,uint256,uint256)") {
1784 return self.handle_bound_uint(state, args_offset);
1785 }
1786 if selector == selector!("bound(int256,int256,int256)") {
1787 return self.handle_bound_int(state, args_offset);
1788 }
1789 if selector == selector!("envExists(string)") {
1790 let name = read_abi_string_arg(&state.memory, args_offset, 0, "symbolic vm.envExists")?;
1791 return Ok(CheatcodeOutcome::Continue(vec![SymWord::Concrete(U256::from(
1792 std::env::var_os(name).is_some(),
1793 ))]));
1794 }
1795 if selector == selector!("envBool(string)") {
1796 let name = read_abi_string_arg(&state.memory, args_offset, 0, "symbolic vm.envBool")?;
1797 let value = std::env::var(name)
1798 .map_err(|_| SymbolicError::Unsupported("symbolic env var missing"))?;
1799 return Ok(CheatcodeOutcome::Continue(vec![SymWord::Concrete(U256::from(
1800 parse_env_bool(&value)?,
1801 ))]));
1802 }
1803 if selector == selector!("envUint(string)") {
1804 let name = read_abi_string_arg(&state.memory, args_offset, 0, "symbolic vm.envUint")?;
1805 let value = std::env::var(name)
1806 .map_err(|_| SymbolicError::Unsupported("symbolic env var missing"))?;
1807 return Ok(CheatcodeOutcome::Continue(vec![SymWord::Concrete(parse_env_uint(
1808 &value,
1809 )?)]));
1810 }
1811 if selector == selector!("envInt(string)") {
1812 let name = read_abi_string_arg(&state.memory, args_offset, 0, "symbolic vm.envInt")?;
1813 let value = std::env::var(name)
1814 .map_err(|_| SymbolicError::Unsupported("symbolic env var missing"))?;
1815 return Ok(CheatcodeOutcome::Continue(vec![SymWord::Concrete(parse_env_int(&value)?)]));
1816 }
1817 if selector == selector!("envAddress(string)") {
1818 let name =
1819 read_abi_string_arg(&state.memory, args_offset, 0, "symbolic vm.envAddress")?;
1820 let value = std::env::var(name)
1821 .map_err(|_| SymbolicError::Unsupported("symbolic env var missing"))?;
1822 let address = parse_env_address(&value)?;
1823 return Ok(CheatcodeOutcome::Continue(vec![SymWord::Concrete(address_word(address))]));
1824 }
1825 if selector == selector!("envBytes32(string)") {
1826 let name =
1827 read_abi_string_arg(&state.memory, args_offset, 0, "symbolic vm.envBytes32")?;
1828 let value = std::env::var(name)
1829 .map_err(|_| SymbolicError::Unsupported("symbolic env var missing"))?;
1830 return Ok(CheatcodeOutcome::Continue(vec![SymWord::Concrete(parse_env_bytes32(
1831 &value,
1832 )?)]));
1833 }
1834 if selector == selector!("envString(string)") {
1835 let name = read_abi_string_arg(&state.memory, args_offset, 0, "symbolic vm.envString")?;
1836 let value = std::env::var(name)
1837 .map_err(|_| SymbolicError::Unsupported("symbolic env var missing"))?;
1838 return Ok(CheatcodeOutcome::ContinueData(abi_concrete_bytes_return(value.bytes())));
1839 }
1840 if selector == selector!("envBytes(string)") {
1841 let name = read_abi_string_arg(&state.memory, args_offset, 0, "symbolic vm.envBytes")?;
1842 let value = std::env::var(name)
1843 .map_err(|_| SymbolicError::Unsupported("symbolic env var missing"))?;
1844 return Ok(CheatcodeOutcome::ContinueData(abi_concrete_bytes_return(parse_env_bytes(
1845 &value,
1846 )?)));
1847 }
1848 if selector == selector!("envBool(string,string)")
1849 || selector == selector!("envUint(string,string)")
1850 || selector == selector!("envInt(string,string)")
1851 || selector == selector!("envAddress(string,string)")
1852 || selector == selector!("envBytes32(string,string)")
1853 || selector == selector!("envString(string,string)")
1854 || selector == selector!("envBytes(string,string)")
1855 {
1856 let values = decode_cheatcode_args(
1857 state,
1858 in_offset,
1859 in_size,
1860 vec![DynSolType::String, DynSolType::String],
1861 )?;
1862 let name = dyn_string(&values[0])?;
1863 let delimiter = dyn_string(&values[1])?;
1864 let value = std::env::var(name)
1865 .map_err(|_| SymbolicError::Unsupported("symbolic env var missing"))?;
1866 let value = if selector == selector!("envBool(string,string)") {
1867 parse_env_array(&value, &delimiter, parse_env_bool_value)?
1868 } else if selector == selector!("envUint(string,string)") {
1869 parse_env_array(&value, &delimiter, parse_env_uint_value)?
1870 } else if selector == selector!("envInt(string,string)") {
1871 parse_env_array(&value, &delimiter, parse_env_int_value)?
1872 } else if selector == selector!("envAddress(string,string)") {
1873 parse_env_array(&value, &delimiter, parse_env_address_value)?
1874 } else if selector == selector!("envBytes32(string,string)") {
1875 parse_env_array(&value, &delimiter, parse_env_bytes32_value)?
1876 } else if selector == selector!("envString(string,string)") {
1877 parse_env_array(&value, &delimiter, parse_env_string_value)?
1878 } else {
1879 parse_env_array(&value, &delimiter, parse_env_bytes_value)?
1880 };
1881 return Ok(CheatcodeOutcome::ContinueData(abi_concrete_value_return(value)));
1882 }
1883 if selector == selector!("envOr(string,bool)") {
1884 let name = read_abi_string_arg(&state.memory, args_offset, 0, "symbolic vm.envOr")?;
1885 let value = match std::env::var(name) {
1886 Ok(value) => U256::from(parse_env_bool(&value)?),
1887 Err(_) => {
1888 read_abi_concrete_word_arg(&state.memory, args_offset, 1, "symbolic vm.envOr")?
1889 }
1890 };
1891 return Ok(CheatcodeOutcome::Continue(vec![SymWord::Concrete(value)]));
1892 }
1893 if selector == selector!("envOr(string,uint256)")
1894 || selector == selector!("envOr(string,int256)")
1895 || selector == selector!("envOr(string,address)")
1896 || selector == selector!("envOr(string,bytes32)")
1897 {
1898 let name = read_abi_string_arg(&state.memory, args_offset, 0, "symbolic vm.envOr")?;
1899 let default =
1900 read_abi_concrete_word_arg(&state.memory, args_offset, 1, "symbolic vm.envOr")?;
1901 let value = match std::env::var(name) {
1902 Ok(value) if selector == selector!("envOr(string,uint256)") => {
1903 parse_env_uint(&value)?
1904 }
1905 Ok(value) if selector == selector!("envOr(string,int256)") => {
1906 parse_env_int(&value)?
1907 }
1908 Ok(value) if selector == selector!("envOr(string,address)") => {
1909 address_word(parse_env_address(&value)?)
1910 }
1911 Ok(value) => parse_env_bytes32(&value)?,
1912 Err(_) => default,
1913 };
1914 return Ok(CheatcodeOutcome::Continue(vec![SymWord::Concrete(value)]));
1915 }
1916 if selector == selector!("envOr(string,string)") {
1917 let values = decode_cheatcode_args(
1918 state,
1919 in_offset,
1920 in_size,
1921 vec![DynSolType::String, DynSolType::String],
1922 )?;
1923 let name = dyn_string(&values[0])?;
1924 let value = std::env::var(name).unwrap_or(dyn_string(&values[1])?);
1925 return Ok(CheatcodeOutcome::ContinueData(abi_concrete_bytes_return(value.bytes())));
1926 }
1927 if selector == selector!("envOr(string,bytes)") {
1928 let values = decode_cheatcode_args(
1929 state,
1930 in_offset,
1931 in_size,
1932 vec![DynSolType::String, DynSolType::Bytes],
1933 )?;
1934 let name = dyn_string(&values[0])?;
1935 let value = match std::env::var(name) {
1936 Ok(value) => parse_env_bytes(&value)?,
1937 Err(_) => dyn_bytes(&values[1])?,
1938 };
1939 return Ok(CheatcodeOutcome::ContinueData(abi_concrete_bytes_return(value)));
1940 }
1941 if selector == selector!("envOr(string,string,bool[])")
1942 || selector == selector!("envOr(string,string,uint256[])")
1943 || selector == selector!("envOr(string,string,int256[])")
1944 || selector == selector!("envOr(string,string,address[])")
1945 || selector == selector!("envOr(string,string,bytes32[])")
1946 || selector == selector!("envOr(string,string,string[])")
1947 || selector == selector!("envOr(string,string,bytes[])")
1948 {
1949 let element_ty = if selector == selector!("envOr(string,string,bool[])") {
1950 DynSolType::Bool
1951 } else if selector == selector!("envOr(string,string,uint256[])") {
1952 DynSolType::Uint(256)
1953 } else if selector == selector!("envOr(string,string,int256[])") {
1954 DynSolType::Int(256)
1955 } else if selector == selector!("envOr(string,string,address[])") {
1956 DynSolType::Address
1957 } else if selector == selector!("envOr(string,string,bytes32[])") {
1958 DynSolType::FixedBytes(32)
1959 } else if selector == selector!("envOr(string,string,string[])") {
1960 DynSolType::String
1961 } else {
1962 DynSolType::Bytes
1963 };
1964 let values = decode_cheatcode_args(
1965 state,
1966 in_offset,
1967 in_size,
1968 vec![
1969 DynSolType::String,
1970 DynSolType::String,
1971 DynSolType::Array(Box::new(element_ty)),
1972 ],
1973 )?;
1974 let name = dyn_string(&values[0])?;
1975 let delimiter = dyn_string(&values[1])?;
1976 let value = match std::env::var(name) {
1977 Ok(value) if selector == selector!("envOr(string,string,bool[])") => {
1978 parse_env_array(&value, &delimiter, parse_env_bool_value)?
1979 }
1980 Ok(value) if selector == selector!("envOr(string,string,uint256[])") => {
1981 parse_env_array(&value, &delimiter, parse_env_uint_value)?
1982 }
1983 Ok(value) if selector == selector!("envOr(string,string,int256[])") => {
1984 parse_env_array(&value, &delimiter, parse_env_int_value)?
1985 }
1986 Ok(value) if selector == selector!("envOr(string,string,address[])") => {
1987 parse_env_array(&value, &delimiter, parse_env_address_value)?
1988 }
1989 Ok(value) if selector == selector!("envOr(string,string,bytes32[])") => {
1990 parse_env_array(&value, &delimiter, parse_env_bytes32_value)?
1991 }
1992 Ok(value) if selector == selector!("envOr(string,string,string[])") => {
1993 parse_env_array(&value, &delimiter, parse_env_string_value)?
1994 }
1995 Ok(value) => parse_env_array(&value, &delimiter, parse_env_bytes_value)?,
1996 Err(_) => values[2].clone(),
1997 };
1998 return Ok(CheatcodeOutcome::ContinueData(abi_concrete_value_return(value)));
1999 }
2000 if selector == selector!("ffi(string[])") {
2001 if !state.ffi_enabled {
2002 return Err(SymbolicError::Unsupported("symbolic ffi disabled"));
2003 }
2004 let values = decode_cheatcode_args(
2005 state,
2006 in_offset,
2007 in_size,
2008 vec![DynSolType::Array(Box::new(DynSolType::String))],
2009 )?;
2010 let args = dyn_string_array(&values[0])?;
2011 if args.is_empty() || args[0].is_empty() {
2012 return Err(SymbolicError::Unsupported("symbolic ffi empty command"));
2013 }
2014 let output = Command::new(&args[0])
2015 .args(&args[1..])
2016 .output()
2017 .map_err(|_| SymbolicError::Unsupported("symbolic ffi command"))?;
2018 if !output.status.success() {
2019 return Err(SymbolicError::Unsupported("symbolic ffi command failed"));
2020 }
2021 let stdout = String::from_utf8(output.stdout)
2022 .map_err(|_| SymbolicError::Unsupported("symbolic ffi stdout"))?;
2023 let trimmed = stdout.trim();
2024 let bytes = hex::decode(trimmed).unwrap_or_else(|_| trimmed.as_bytes().to_vec());
2025 return Ok(CheatcodeOutcome::ContinueData(abi_concrete_bytes_return(bytes)));
2026 }
2027 if selector == selector!("assertTrue(bool)")
2028 || selector == selector!("assertTrue(bool,string)")
2029 {
2030 let condition = read_abi_word_arg(&state.memory, args_offset, 0)?.nonzero_bool();
2031 return self.handle_assertion(state, condition);
2032 }
2033 if selector == selector!("assertFalse(bool)")
2034 || selector == selector!("assertFalse(bool,string)")
2035 {
2036 let condition = read_abi_word_arg(&state.memory, args_offset, 0)?.into_zero_bool();
2037 return self.handle_assertion(state, condition);
2038 }
2039 if selector == selector!("assertEq(uint256,uint256)")
2040 || selector == selector!("assertEq(uint256,uint256,string)")
2041 || selector == selector!("assertEq(int256,int256)")
2042 || selector == selector!("assertEq(int256,int256,string)")
2043 || selector == selector!("assertEq(address,address)")
2044 || selector == selector!("assertEq(address,address,string)")
2045 || selector == selector!("assertEq(bytes32,bytes32)")
2046 || selector == selector!("assertEq(bytes32,bytes32,string)")
2047 || selector == selector!("assertEq(bool,bool)")
2048 || selector == selector!("assertEq(bool,bool,string)")
2049 {
2050 let left = read_abi_word_arg(&state.memory, args_offset, 0)?;
2051 let right = read_abi_word_arg(&state.memory, args_offset, 1)?;
2052 return self.handle_assertion(state, BoolExpr::eq(left.into_expr(), right.into_expr()));
2053 }
2054 if selector == selector!("assertEq(string,string)")
2055 || selector == selector!("assertEq(string,string,string)")
2056 {
2057 let values = decode_cheatcode_args(
2058 state,
2059 in_offset,
2060 in_size,
2061 if selector == selector!("assertEq(string,string)") {
2062 vec![DynSolType::String, DynSolType::String]
2063 } else {
2064 vec![DynSolType::String, DynSolType::String, DynSolType::String]
2065 },
2066 )?;
2067 return self.handle_assertion(
2068 state,
2069 BoolExpr::Const(dyn_string(&values[0])? == dyn_string(&values[1])?),
2070 );
2071 }
2072 if selector == selector!("assertEq(bytes,bytes)")
2073 || selector == selector!("assertEq(bytes,bytes,string)")
2074 {
2075 let values = decode_cheatcode_args(
2076 state,
2077 in_offset,
2078 in_size,
2079 if selector == selector!("assertEq(bytes,bytes)") {
2080 vec![DynSolType::Bytes, DynSolType::Bytes]
2081 } else {
2082 vec![DynSolType::Bytes, DynSolType::Bytes, DynSolType::String]
2083 },
2084 )?;
2085 return self.handle_assertion(
2086 state,
2087 BoolExpr::Const(dyn_bytes(&values[0])? == dyn_bytes(&values[1])?),
2088 );
2089 }
2090 if selector == selector!("assertEq(bool[],bool[])")
2091 || selector == selector!("assertEq(bool[],bool[],string)")
2092 || selector == selector!("assertEq(uint256[],uint256[])")
2093 || selector == selector!("assertEq(uint256[],uint256[],string)")
2094 || selector == selector!("assertEq(int256[],int256[])")
2095 || selector == selector!("assertEq(int256[],int256[],string)")
2096 || selector == selector!("assertEq(address[],address[])")
2097 || selector == selector!("assertEq(address[],address[],string)")
2098 || selector == selector!("assertEq(bytes32[],bytes32[])")
2099 || selector == selector!("assertEq(bytes32[],bytes32[],string)")
2100 || selector == selector!("assertEq(string[],string[])")
2101 || selector == selector!("assertEq(string[],string[],string)")
2102 || selector == selector!("assertEq(bytes[],bytes[])")
2103 || selector == selector!("assertEq(bytes[],bytes[],string)")
2104 {
2105 let element_ty = array_assertion_element_type(selector)?;
2106 let values = decode_cheatcode_args(
2107 state,
2108 in_offset,
2109 in_size,
2110 if selector_has_string_reason(selector) {
2111 vec![
2112 DynSolType::Array(Box::new(element_ty.clone())),
2113 DynSolType::Array(Box::new(element_ty)),
2114 DynSolType::String,
2115 ]
2116 } else {
2117 vec![
2118 DynSolType::Array(Box::new(element_ty.clone())),
2119 DynSolType::Array(Box::new(element_ty)),
2120 ]
2121 },
2122 )?;
2123 return self.handle_assertion(state, BoolExpr::Const(values[0] == values[1]));
2124 }
2125 if selector == selector!("assertEqDecimal(uint256,uint256,uint256)")
2126 || selector == selector!("assertEqDecimal(uint256,uint256,uint256,string)")
2127 || selector == selector!("assertEqDecimal(int256,int256,uint256)")
2128 || selector == selector!("assertEqDecimal(int256,int256,uint256,string)")
2129 {
2130 let left = read_abi_word_arg(&state.memory, args_offset, 0)?;
2131 let right = read_abi_word_arg(&state.memory, args_offset, 1)?;
2132 return self.handle_assertion(state, BoolExpr::eq(left.into_expr(), right.into_expr()));
2133 }
2134 if selector == selector!("assertNotEq(uint256,uint256)")
2135 || selector == selector!("assertNotEq(uint256,uint256,string)")
2136 || selector == selector!("assertNotEq(int256,int256)")
2137 || selector == selector!("assertNotEq(int256,int256,string)")
2138 || selector == selector!("assertNotEq(address,address)")
2139 || selector == selector!("assertNotEq(address,address,string)")
2140 || selector == selector!("assertNotEq(bytes32,bytes32)")
2141 || selector == selector!("assertNotEq(bytes32,bytes32,string)")
2142 || selector == selector!("assertNotEq(bool,bool)")
2143 || selector == selector!("assertNotEq(bool,bool,string)")
2144 {
2145 let left = read_abi_word_arg(&state.memory, args_offset, 0)?;
2146 let right = read_abi_word_arg(&state.memory, args_offset, 1)?;
2147 return self
2148 .handle_assertion(state, BoolExpr::eq(left.into_expr(), right.into_expr()).not());
2149 }
2150 if selector == selector!("assertNotEq(string,string)")
2151 || selector == selector!("assertNotEq(string,string,string)")
2152 {
2153 let values = decode_cheatcode_args(
2154 state,
2155 in_offset,
2156 in_size,
2157 if selector == selector!("assertNotEq(string,string)") {
2158 vec![DynSolType::String, DynSolType::String]
2159 } else {
2160 vec![DynSolType::String, DynSolType::String, DynSolType::String]
2161 },
2162 )?;
2163 return self.handle_assertion(
2164 state,
2165 BoolExpr::Const(dyn_string(&values[0])? != dyn_string(&values[1])?),
2166 );
2167 }
2168 if selector == selector!("assertNotEq(bytes,bytes)")
2169 || selector == selector!("assertNotEq(bytes,bytes,string)")
2170 {
2171 let values = decode_cheatcode_args(
2172 state,
2173 in_offset,
2174 in_size,
2175 if selector == selector!("assertNotEq(bytes,bytes)") {
2176 vec![DynSolType::Bytes, DynSolType::Bytes]
2177 } else {
2178 vec![DynSolType::Bytes, DynSolType::Bytes, DynSolType::String]
2179 },
2180 )?;
2181 return self.handle_assertion(
2182 state,
2183 BoolExpr::Const(dyn_bytes(&values[0])? != dyn_bytes(&values[1])?),
2184 );
2185 }
2186 if selector == selector!("assertNotEq(bool[],bool[])")
2187 || selector == selector!("assertNotEq(bool[],bool[],string)")
2188 || selector == selector!("assertNotEq(uint256[],uint256[])")
2189 || selector == selector!("assertNotEq(uint256[],uint256[],string)")
2190 || selector == selector!("assertNotEq(int256[],int256[])")
2191 || selector == selector!("assertNotEq(int256[],int256[],string)")
2192 || selector == selector!("assertNotEq(address[],address[])")
2193 || selector == selector!("assertNotEq(address[],address[],string)")
2194 || selector == selector!("assertNotEq(bytes32[],bytes32[])")
2195 || selector == selector!("assertNotEq(bytes32[],bytes32[],string)")
2196 || selector == selector!("assertNotEq(string[],string[])")
2197 || selector == selector!("assertNotEq(string[],string[],string)")
2198 || selector == selector!("assertNotEq(bytes[],bytes[])")
2199 || selector == selector!("assertNotEq(bytes[],bytes[],string)")
2200 {
2201 let element_ty = array_assertion_element_type(selector)?;
2202 let values = decode_cheatcode_args(
2203 state,
2204 in_offset,
2205 in_size,
2206 if selector_has_string_reason(selector) {
2207 vec![
2208 DynSolType::Array(Box::new(element_ty.clone())),
2209 DynSolType::Array(Box::new(element_ty)),
2210 DynSolType::String,
2211 ]
2212 } else {
2213 vec![
2214 DynSolType::Array(Box::new(element_ty.clone())),
2215 DynSolType::Array(Box::new(element_ty)),
2216 ]
2217 },
2218 )?;
2219 return self.handle_assertion(state, BoolExpr::Const(values[0] != values[1]));
2220 }
2221 if selector == selector!("assertLt(uint256,uint256)")
2222 || selector == selector!("assertLt(uint256,uint256,string)")
2223 {
2224 let left = read_abi_word_arg(&state.memory, args_offset, 0)?;
2225 let right = read_abi_word_arg(&state.memory, args_offset, 1)?;
2226 return self.handle_assertion(
2227 state,
2228 BoolExpr::cmp(BoolExprOp::Ult, left.into_expr(), right.into_expr()),
2229 );
2230 }
2231 if selector == selector!("assertLe(uint256,uint256)")
2232 || selector == selector!("assertLe(uint256,uint256,string)")
2233 {
2234 let left = read_abi_word_arg(&state.memory, args_offset, 0)?;
2235 let right = read_abi_word_arg(&state.memory, args_offset, 1)?;
2236 return self.handle_assertion(
2237 state,
2238 BoolExpr::cmp(BoolExprOp::Ule, left.into_expr(), right.into_expr()),
2239 );
2240 }
2241 if selector == selector!("assertGt(uint256,uint256)")
2242 || selector == selector!("assertGt(uint256,uint256,string)")
2243 {
2244 let left = read_abi_word_arg(&state.memory, args_offset, 0)?;
2245 let right = read_abi_word_arg(&state.memory, args_offset, 1)?;
2246 return self.handle_assertion(
2247 state,
2248 BoolExpr::cmp(BoolExprOp::Ugt, left.into_expr(), right.into_expr()),
2249 );
2250 }
2251 if selector == selector!("assertGe(uint256,uint256)")
2252 || selector == selector!("assertGe(uint256,uint256,string)")
2253 {
2254 let left = read_abi_word_arg(&state.memory, args_offset, 0)?;
2255 let right = read_abi_word_arg(&state.memory, args_offset, 1)?;
2256 return self.handle_assertion(
2257 state,
2258 BoolExpr::cmp(BoolExprOp::Uge, left.into_expr(), right.into_expr()),
2259 );
2260 }
2261 if selector == selector!("assertLt(int256,int256)")
2262 || selector == selector!("assertLt(int256,int256,string)")
2263 {
2264 let left = read_abi_word_arg(&state.memory, args_offset, 0)?;
2265 let right = read_abi_word_arg(&state.memory, args_offset, 1)?;
2266 return self.handle_assertion(
2267 state,
2268 BoolExpr::cmp(BoolExprOp::Slt, left.into_expr(), right.into_expr()),
2269 );
2270 }
2271 if selector == selector!("assertGt(int256,int256)")
2272 || selector == selector!("assertGt(int256,int256,string)")
2273 {
2274 let left = read_abi_word_arg(&state.memory, args_offset, 0)?;
2275 let right = read_abi_word_arg(&state.memory, args_offset, 1)?;
2276 return self.handle_assertion(
2277 state,
2278 BoolExpr::cmp(BoolExprOp::Sgt, left.into_expr(), right.into_expr()),
2279 );
2280 }
2281 if selector == selector!("assertLe(int256,int256)")
2282 || selector == selector!("assertLe(int256,int256,string)")
2283 {
2284 let left = read_abi_word_arg(&state.memory, args_offset, 0)?;
2285 let right = read_abi_word_arg(&state.memory, args_offset, 1)?;
2286 return self.handle_assertion(
2287 state,
2288 BoolExpr::cmp(BoolExprOp::Sgt, left.into_expr(), right.into_expr()).not(),
2289 );
2290 }
2291 if selector == selector!("assertGe(int256,int256)")
2292 || selector == selector!("assertGe(int256,int256,string)")
2293 {
2294 let left = read_abi_word_arg(&state.memory, args_offset, 0)?;
2295 let right = read_abi_word_arg(&state.memory, args_offset, 1)?;
2296 return self.handle_assertion(
2297 state,
2298 BoolExpr::cmp(BoolExprOp::Slt, left.into_expr(), right.into_expr()).not(),
2299 );
2300 }
2301 if selector == selector!("randomUint()") {
2302 return Ok(CheatcodeOutcome::Continue(vec![state.fresh_word("vmRandomUint")]));
2303 }
2304 if selector == selector!("randomUint(uint256)") {
2305 let bits =
2306 read_abi_constrained_word_arg(state, args_offset, 0, "symbolic randomUint bits")?;
2307 Self::validate_symbolic_integer_bits(bits, "symbolic randomUint bits")?;
2308 return Ok(CheatcodeOutcome::Continue(vec![state.fresh_bounded_uint(bits)]));
2309 }
2310 if selector == selector!("randomUint(uint256,uint256)") {
2311 let min = state.memory.load_word(in_offset + 4)?;
2312 let max = state.memory.load_word(in_offset + 36)?;
2313 let value = state.fresh_word("vmRandomUintRange");
2314 state.constraints.push(BoolExpr::cmp(
2315 BoolExprOp::Uge,
2316 value.clone().into_expr(),
2317 min.into_expr(),
2318 ));
2319 state.constraints.push(BoolExpr::cmp(
2320 BoolExprOp::Ule,
2321 value.clone().into_expr(),
2322 max.into_expr(),
2323 ));
2324 return Ok(CheatcodeOutcome::Continue(vec![value]));
2325 }
2326 if selector == selector!("randomInt()") {
2327 return Ok(CheatcodeOutcome::Continue(vec![state.fresh_word("vmRandomInt")]));
2328 }
2329 if selector == selector!("randomInt(uint256)") {
2330 let bits =
2331 read_abi_constrained_word_arg(state, args_offset, 0, "symbolic randomInt bits")?;
2332 Self::validate_symbolic_integer_bits(bits, "symbolic randomInt bits")?;
2333 return Ok(CheatcodeOutcome::Continue(vec![state.fresh_bounded_int(bits)]));
2334 }
2335 if selector == selector!("randomAddress()") {
2336 let value = state.fresh_bounded_uint(U256::from(160));
2337 return Ok(CheatcodeOutcome::Continue(vec![value]));
2338 }
2339 if selector == selector!("randomBool()") {
2340 let value = state.fresh_bounded_uint(U256::from(1));
2341 return Ok(CheatcodeOutcome::Continue(vec![value]));
2342 }
2343 if selector == selector!("randomBytes(uint256)") {
2344 let len = read_abi_word_arg(&state.memory, args_offset, 0)?;
2345 let max_limit = self.config.max_dynamic_length as usize;
2346 let max_len = state
2347 .upper_bound_usize(&len)
2348 .filter(|len| *len <= max_limit)
2349 .map(Ok)
2350 .unwrap_or_else(|| {
2351 self.solver_upper_bound_usize(
2352 state,
2353 &len,
2354 max_limit,
2355 "symbolic randomBytes length",
2356 )
2357 })?;
2358 let bytes = (0..max_len).map(|_| state.fresh_bounded_uint(U256::from(8))).collect();
2359 return Ok(CheatcodeOutcome::ContinueData(abi_bytes_return_with_len(len, bytes)));
2360 }
2361 if selector == selector!("randomBytes4()") {
2362 let value = state.fresh_bounded_uint(U256::from(32));
2363 return Ok(CheatcodeOutcome::Continue(vec![shift_left(value, 224)]));
2364 }
2365 if selector == selector!("randomBytes8()") {
2366 let value = state.fresh_bounded_uint(U256::from(64));
2367 return Ok(CheatcodeOutcome::Continue(vec![shift_left(value, 192)]));
2368 }
2369
2370 Err(SymbolicError::Unsupported("symbolic Foundry cheatcode"))
2371 }
2372
2373 pub(super) fn handle_symbolic_vm_cheatcode(
2375 &mut self,
2376 state: &mut PathState,
2377 selector: [u8; 4],
2378 in_offset: usize,
2379 ) -> Result<SymReturnData, SymbolicError> {
2380 if selector == selector!("createUint256(string)")
2381 || selector == selector!("createInt256(string)")
2382 || selector == selector!("createBytes32(string)")
2383 {
2384 return Ok(SymReturnData::from_words(vec![state.fresh_word("svm")]));
2385 }
2386 for bits in (8..=256).step_by(8) {
2387 if selector == selector_for(&format!("createUint{bits}(string)")) {
2388 if bits == 256 {
2389 return Ok(SymReturnData::from_words(vec![state.fresh_word("svm")]));
2390 }
2391 return Ok(SymReturnData::from_words(vec![
2392 state.fresh_bounded_uint(U256::from(bits)),
2393 ]));
2394 }
2395 if selector == selector_for(&format!("createInt{bits}(string)")) {
2396 if bits == 256 {
2397 return Ok(SymReturnData::from_words(vec![state.fresh_word("svm")]));
2398 }
2399 return Ok(SymReturnData::from_words(vec![
2400 state.fresh_bounded_int(U256::from(bits)),
2401 ]));
2402 }
2403 }
2404 for bytes in 1..=32 {
2405 if selector == selector_for(&format!("createBytes{bytes}(string)")) {
2406 let value = state.fresh_bounded_uint(U256::from(bytes * 8));
2407 let value = if bytes == 32 { value } else { shift_left(value, (32 - bytes) * 8) };
2408 return Ok(SymReturnData::from_words(vec![value]));
2409 }
2410 }
2411 if selector == selector!("createUint(uint256,string)") {
2412 let bits = read_abi_constrained_word_arg(
2413 state,
2414 in_offset + 4,
2415 0,
2416 "symbolic svm.create integer bits",
2417 )?;
2418 Self::validate_symbolic_integer_bits(bits, "symbolic svm.create integer bits")?;
2419 return Ok(SymReturnData::from_words(vec![state.fresh_bounded_uint(bits)]));
2420 }
2421 if selector == selector!("createInt(uint256,string)") {
2422 let bits = read_abi_constrained_word_arg(
2423 state,
2424 in_offset + 4,
2425 0,
2426 "symbolic svm.create integer bits",
2427 )?;
2428 Self::validate_symbolic_integer_bits(bits, "symbolic svm.create integer bits")?;
2429 return Ok(SymReturnData::from_words(vec![state.fresh_bounded_int(bits)]));
2430 }
2431 if selector == selector!("createAddress(string)") {
2432 return Ok(SymReturnData::from_words(vec![state.fresh_bounded_uint(U256::from(160))]));
2433 }
2434 if selector == selector!("createBool(string)") {
2435 return Ok(SymReturnData::from_words(vec![state.fresh_bounded_uint(U256::from(1))]));
2436 }
2437 if selector == selector!("createBytes(string)") {
2438 let len = self.config.default_dynamic_length as usize;
2439 let bytes = (0..len).map(|_| state.fresh_bounded_uint(U256::from(8))).collect();
2440 return Ok(abi_bytes_return(bytes));
2441 }
2442 if selector == selector!("createBytes(uint256,string)") {
2443 let len = read_abi_constrained_word_arg(
2444 state,
2445 in_offset + 4,
2446 0,
2447 "symbolic svm.createBytes length",
2448 )?;
2449 let len = u256_to_usize(len)
2450 .filter(|len| *len <= self.config.max_calldata_bytes as usize)
2451 .ok_or(SymbolicError::Unsupported("symbolic svm.createBytes length"))?;
2452 let bytes = (0..len).map(|_| state.fresh_bounded_uint(U256::from(8))).collect();
2453 return Ok(abi_bytes_return(bytes));
2454 }
2455 if selector == selector!("createString(string)") {
2456 let len = self.config.default_dynamic_length as usize;
2457 let bytes = (0..len)
2458 .map(|_| {
2459 let byte = state.fresh_bounded_uint(U256::from(8));
2460 state.constraints.push(BoolExpr::cmp(
2461 BoolExprOp::Uge,
2462 byte.clone().into_expr(),
2463 Expr::Const(U256::from(0x20)),
2464 ));
2465 state.constraints.push(BoolExpr::cmp(
2466 BoolExprOp::Ule,
2467 byte.clone().into_expr(),
2468 Expr::Const(U256::from(0x7e)),
2469 ));
2470 byte
2471 })
2472 .collect();
2473 return Ok(abi_bytes_return(bytes));
2474 }
2475 if selector == selector!("createString(uint256,string)") {
2476 let len = read_abi_constrained_word_arg(
2477 state,
2478 in_offset + 4,
2479 0,
2480 "symbolic svm.createString length",
2481 )?;
2482 let len = u256_to_usize(len)
2483 .filter(|len| *len <= self.config.max_calldata_bytes as usize)
2484 .ok_or(SymbolicError::Unsupported("symbolic svm.createString length"))?;
2485 let bytes = (0..len)
2486 .map(|_| {
2487 let byte = state.fresh_bounded_uint(U256::from(8));
2488 state.constraints.push(BoolExpr::cmp(
2489 BoolExprOp::Uge,
2490 byte.clone().into_expr(),
2491 Expr::Const(U256::from(0x20)),
2492 ));
2493 state.constraints.push(BoolExpr::cmp(
2494 BoolExprOp::Ule,
2495 byte.clone().into_expr(),
2496 Expr::Const(U256::from(0x7e)),
2497 ));
2498 byte
2499 })
2500 .collect();
2501 return Ok(abi_bytes_return(bytes));
2502 }
2503 if selector == selector!("createBytes4(string)") {
2504 return Ok(SymReturnData::from_words(vec![shift_left(
2505 state.fresh_bounded_uint(U256::from(32)),
2506 224,
2507 )]));
2508 }
2509 if selector == selector!("createCalldata(string)") {
2510 let max = self.config.max_calldata_bytes as usize;
2511 let len = if max < 4 {
2512 max
2513 } else {
2514 (self.config.default_dynamic_length as usize).max(4).min(max)
2515 };
2516 let bytes = (0..len).map(|_| state.fresh_bounded_uint(U256::from(8))).collect();
2517 return Ok(abi_bytes_return(bytes));
2518 }
2519 if selector == selector!("enableSymbolicStorage(address)")
2520 || selector == selector!("setArbitraryStorage(address)")
2521 {
2522 let target = read_abi_address_or_symbolic_slot_arg(state, in_offset + 4, 0)?;
2523 state.world.enable_arbitrary_storage(target);
2524 return Ok(SymReturnData::default());
2525 }
2526 if selector == selector!("snapshotStorage(address)") {
2527 let _target = read_abi_address_or_symbolic_slot_arg(state, in_offset + 4, 0)?;
2528 let id = state.world.snapshot_state();
2529 return Ok(SymReturnData::from_words(vec![SymWord::Concrete(id)]));
2530 }
2531 if selector == selector!("snapshotState()") {
2532 let id = state.world.snapshot_state();
2533 return Ok(SymReturnData::from_words(vec![SymWord::Concrete(id)]));
2534 }
2535
2536 Err(SymbolicError::Unsupported("symbolic VM compatibility cheatcode"))
2537 }
2538}