Skip to main content

foundry_evm_symbolic/executor/
cheatcodes.rs

1use super::*;
2
3impl SymbolicExecutor {
4    /// Runs the `handle_assertion` symbolic executor helper.
5    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    /// Applies the `set_expected_revert` symbolic executor helper.
33    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    /// Applies the `set_expected_emit` symbolic executor helper.
46    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    /// Applies the `set_expected_call` symbolic executor helper.
60    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    /// Applies the `set_expected_create` symbolic executor helper.
85    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    /// Applies the `observe_expected_create` symbolic executor helper.
97    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    /// Implements the `branch_accesses_cheatcode_if_needed` symbolic executor helper.
139    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    /// Implements the `accesses_return_data_for_target` symbolic executor helper.
207    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    /// Implements the `add_call_mock` symbolic executor helper.
248    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    /// Applies the `set_function_mock` symbolic executor helper.
262    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    /// Runs the `handle_foundry_cheatcode` symbolic executor helper.
280    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    /// Runs the `handle_symbolic_vm_cheatcode` symbolic executor helper.
2374    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}