foundry_cheatcodes/
test.rs1use crate::{Cheatcode, Cheatcodes, CheatsCtxt, Result, Vm::*};
4use alloy_chains::Chain as AlloyChain;
5use alloy_primitives::{Address, U256};
6use alloy_sol_types::SolValue;
7use foundry_common::version::SEMVER_VERSION;
8use foundry_evm_core::{constants::MAGIC_SKIP, evm::FoundryEvmNetwork};
9use revm::context::{ContextTr, JournalTr};
10use std::str::FromStr;
11
12pub(crate) mod assert;
13pub(crate) mod assume;
14pub(crate) mod expect;
15pub(crate) mod revert_handlers;
16
17impl Cheatcode for breakpoint_0Call {
18 fn apply_stateful<FEN: FoundryEvmNetwork>(&self, ccx: &mut CheatsCtxt<'_, '_, FEN>) -> Result {
19 let Self { char } = self;
20 breakpoint(ccx.state, &ccx.caller, char, true)
21 }
22}
23
24impl Cheatcode for breakpoint_1Call {
25 fn apply_stateful<FEN: FoundryEvmNetwork>(&self, ccx: &mut CheatsCtxt<'_, '_, FEN>) -> Result {
26 let Self { char, value } = self;
27 breakpoint(ccx.state, &ccx.caller, char, *value)
28 }
29}
30
31impl Cheatcode for getFoundryVersionCall {
32 fn apply<FEN: FoundryEvmNetwork>(&self, _state: &mut Cheatcodes<FEN>) -> Result {
33 let Self {} = self;
34 Ok(SEMVER_VERSION.abi_encode())
35 }
36}
37
38impl Cheatcode for rpcUrlCall {
39 fn apply<FEN: FoundryEvmNetwork>(&self, state: &mut Cheatcodes<FEN>) -> Result {
40 let Self { rpcAlias } = self;
41 let url = state.config.rpc_endpoint(rpcAlias)?.url()?.abi_encode();
42 Ok(url)
43 }
44}
45
46impl Cheatcode for rpcUrlsCall {
47 fn apply<FEN: FoundryEvmNetwork>(&self, state: &mut Cheatcodes<FEN>) -> Result {
48 let Self {} = self;
49 state.config.rpc_urls().map(|urls| urls.abi_encode())
50 }
51}
52
53impl Cheatcode for rpcUrlStructsCall {
54 fn apply<FEN: FoundryEvmNetwork>(&self, state: &mut Cheatcodes<FEN>) -> Result {
55 let Self {} = self;
56 state.config.rpc_urls().map(|urls| urls.abi_encode())
57 }
58}
59
60impl Cheatcode for sleepCall {
61 fn apply<FEN: FoundryEvmNetwork>(&self, _state: &mut Cheatcodes<FEN>) -> Result {
62 let Self { duration } = self;
63 let sleep_duration = std::time::Duration::from_millis(duration.saturating_to());
64 std::thread::sleep(sleep_duration);
65 Ok(Default::default())
66 }
67}
68
69impl Cheatcode for skip_0Call {
70 fn apply_stateful<FEN: FoundryEvmNetwork>(&self, ccx: &mut CheatsCtxt<'_, '_, FEN>) -> Result {
71 let Self { skipTest } = *self;
72 if skipTest {
73 ensure!(ccx.ecx.journal().depth() <= 1, "`skip` can only be used at test level");
76 Err([MAGIC_SKIP, &[]].concat().into())
77 } else {
78 Ok(Default::default())
79 }
80 }
81}
82
83impl Cheatcode for skip_1Call {
84 fn apply_stateful<FEN: FoundryEvmNetwork>(&self, ccx: &mut CheatsCtxt<'_, '_, FEN>) -> Result {
85 let Self { skipTest, reason } = self;
86 if *skipTest {
87 ensure!(ccx.ecx.journal().depth() <= 1, "`skip` can only be used at test level");
90 Err([MAGIC_SKIP, reason.as_bytes()].concat().into())
91 } else {
92 Ok(Default::default())
93 }
94 }
95}
96
97impl Cheatcode for getChain_0Call {
98 fn apply<FEN: FoundryEvmNetwork>(&self, state: &mut Cheatcodes<FEN>) -> Result {
99 let Self { chainAlias } = self;
100 get_chain(state, chainAlias)
101 }
102}
103
104impl Cheatcode for getChain_1Call {
105 fn apply<FEN: FoundryEvmNetwork>(&self, state: &mut Cheatcodes<FEN>) -> Result {
106 let Self { chainId } = self;
107 let chain_id_str = chainId.to_string();
109 get_chain(state, &chain_id_str)
110 }
111}
112
113fn breakpoint<FEN: FoundryEvmNetwork>(
115 state: &mut Cheatcodes<FEN>,
116 caller: &Address,
117 s: &str,
118 add: bool,
119) -> Result {
120 let mut chars = s.chars();
121 let (Some(point), None) = (chars.next(), chars.next()) else {
122 bail!("breakpoints must be exactly one character");
123 };
124 ensure!(point.is_alphabetic(), "only alphabetic characters are accepted as breakpoints");
125
126 if add {
127 state.breakpoints.insert(point, (*caller, state.pc));
128 } else {
129 state.breakpoints.remove(&point);
130 }
131
132 Ok(Default::default())
133}
134
135fn get_chain<FEN: FoundryEvmNetwork>(state: &mut Cheatcodes<FEN>, chain_alias: &str) -> Result {
137 let alloy_chain = AlloyChain::from_str(chain_alias)
139 .map_err(|_| fmt_err!("invalid chain alias: {chain_alias}"))?;
140 let chain_name = alloy_chain.to_string();
141 let chain_id = alloy_chain.id();
142
143 if chain_name == chain_id.to_string() {
147 return Err(fmt_err!("invalid chain alias: {chain_alias}"));
148 }
149
150 let (rpc_url, chain_alias) = if let Some(rpc_url) =
152 state.config.rpc_endpoint(&chain_name).ok().and_then(|e| e.url().ok())
153 {
154 (rpc_url, chain_name.clone())
155 } else {
156 (String::new(), chain_alias.to_string())
157 };
158
159 let chain_struct = Chain {
160 name: chain_name,
161 chainId: U256::from(chain_id),
162 chainAlias: chain_alias,
163 rpcUrl: rpc_url,
164 };
165
166 Ok(chain_struct.abi_encode())
167}