foundry_cheatcodes/
test.rs
1use crate::{Cheatcode, Cheatcodes, CheatsCtxt, Result, Vm::*};
4use alloy_primitives::Address;
5use alloy_sol_types::SolValue;
6use foundry_common::version::SEMVER_VERSION;
7use foundry_evm_core::constants::MAGIC_SKIP;
8
9pub(crate) mod assert;
10pub(crate) mod assume;
11pub(crate) mod expect;
12pub(crate) mod revert_handlers;
13
14impl Cheatcode for breakpoint_0Call {
15 fn apply_stateful(&self, ccx: &mut CheatsCtxt) -> Result {
16 let Self { char } = self;
17 breakpoint(ccx.state, &ccx.caller, char, true)
18 }
19}
20
21impl Cheatcode for breakpoint_1Call {
22 fn apply_stateful(&self, ccx: &mut CheatsCtxt) -> Result {
23 let Self { char, value } = self;
24 breakpoint(ccx.state, &ccx.caller, char, *value)
25 }
26}
27
28impl Cheatcode for getFoundryVersionCall {
29 fn apply(&self, _state: &mut Cheatcodes) -> Result {
30 let Self {} = self;
31 Ok(SEMVER_VERSION.abi_encode())
32 }
33}
34
35impl Cheatcode for rpcUrlCall {
36 fn apply(&self, state: &mut Cheatcodes) -> Result {
37 let Self { rpcAlias } = self;
38 let url = state.config.rpc_endpoint(rpcAlias)?.url()?.abi_encode();
39 Ok(url)
40 }
41}
42
43impl Cheatcode for rpcUrlsCall {
44 fn apply(&self, state: &mut Cheatcodes) -> Result {
45 let Self {} = self;
46 state.config.rpc_urls().map(|urls| urls.abi_encode())
47 }
48}
49
50impl Cheatcode for rpcUrlStructsCall {
51 fn apply(&self, state: &mut Cheatcodes) -> Result {
52 let Self {} = self;
53 state.config.rpc_urls().map(|urls| urls.abi_encode())
54 }
55}
56
57impl Cheatcode for sleepCall {
58 fn apply(&self, _state: &mut Cheatcodes) -> Result {
59 let Self { duration } = self;
60 let sleep_duration = std::time::Duration::from_millis(duration.saturating_to());
61 std::thread::sleep(sleep_duration);
62 Ok(Default::default())
63 }
64}
65
66impl Cheatcode for skip_0Call {
67 fn apply_stateful(&self, ccx: &mut CheatsCtxt) -> Result {
68 let Self { skipTest } = *self;
69 skip_1Call { skipTest, reason: String::new() }.apply_stateful(ccx)
70 }
71}
72
73impl Cheatcode for skip_1Call {
74 fn apply_stateful(&self, ccx: &mut CheatsCtxt) -> Result {
75 let Self { skipTest, reason } = self;
76 if *skipTest {
77 ensure!(ccx.ecx.journaled_state.depth() <= 1, "`skip` can only be used at test level");
80 Err([MAGIC_SKIP, reason.as_bytes()].concat().into())
81 } else {
82 Ok(Default::default())
83 }
84 }
85}
86
87fn breakpoint(state: &mut Cheatcodes, caller: &Address, s: &str, add: bool) -> Result {
89 let mut chars = s.chars();
90 let (Some(point), None) = (chars.next(), chars.next()) else {
91 bail!("breakpoints must be exactly one character");
92 };
93 ensure!(point.is_alphabetic(), "only alphabetic characters are accepted as breakpoints");
94
95 if add {
96 state.breakpoints.insert(point, (*caller, state.pc));
97 } else {
98 state.breakpoints.remove(&point);
99 }
100
101 Ok(Default::default())
102}