foundry_cheatcodes/
string.rs1use crate::{Cheatcode, Cheatcodes, Result, Vm::*};
4use alloy_dyn_abi::{DynSolType, DynSolValue};
5use alloy_primitives::{U256, hex};
6use alloy_sol_types::SolValue;
7use foundry_evm_core::evm::FoundryEvmNetwork;
8
9impl Cheatcode for toString_0Call {
11 fn apply<FEN: FoundryEvmNetwork>(&self, _state: &mut Cheatcodes<FEN>) -> Result {
12 let Self { value } = self;
13 Ok(value.to_string().abi_encode())
14 }
15}
16
17impl Cheatcode for toString_1Call {
19 fn apply<FEN: FoundryEvmNetwork>(&self, _state: &mut Cheatcodes<FEN>) -> Result {
20 let Self { value } = self;
21 Ok(value.to_string().abi_encode())
22 }
23}
24
25impl Cheatcode for toString_2Call {
27 fn apply<FEN: FoundryEvmNetwork>(&self, _state: &mut Cheatcodes<FEN>) -> Result {
28 let Self { value } = self;
29 Ok(value.to_string().abi_encode())
30 }
31}
32
33impl Cheatcode for toString_3Call {
35 fn apply<FEN: FoundryEvmNetwork>(&self, _state: &mut Cheatcodes<FEN>) -> Result {
36 let Self { value } = self;
37 Ok(value.to_string().abi_encode())
38 }
39}
40
41impl Cheatcode for toString_4Call {
43 fn apply<FEN: FoundryEvmNetwork>(&self, _state: &mut Cheatcodes<FEN>) -> Result {
44 let Self { value } = self;
45 Ok(value.to_string().abi_encode())
46 }
47}
48
49impl Cheatcode for toString_5Call {
51 fn apply<FEN: FoundryEvmNetwork>(&self, _state: &mut Cheatcodes<FEN>) -> Result {
52 let Self { value } = self;
53 Ok(value.to_string().abi_encode())
54 }
55}
56
57impl Cheatcode for parseBytesCall {
58 fn apply<FEN: FoundryEvmNetwork>(&self, _state: &mut Cheatcodes<FEN>) -> Result {
59 let Self { stringifiedValue } = self;
60 parse(stringifiedValue, &DynSolType::Bytes)
61 }
62}
63
64impl Cheatcode for parseAddressCall {
65 fn apply<FEN: FoundryEvmNetwork>(&self, _state: &mut Cheatcodes<FEN>) -> Result {
66 let Self { stringifiedValue } = self;
67 parse(stringifiedValue, &DynSolType::Address)
68 }
69}
70
71impl Cheatcode for parseUintCall {
72 fn apply<FEN: FoundryEvmNetwork>(&self, _state: &mut Cheatcodes<FEN>) -> Result {
73 let Self { stringifiedValue } = self;
74 parse(stringifiedValue, &DynSolType::Uint(256))
75 }
76}
77
78impl Cheatcode for parseIntCall {
79 fn apply<FEN: FoundryEvmNetwork>(&self, _state: &mut Cheatcodes<FEN>) -> Result {
80 let Self { stringifiedValue } = self;
81 parse(stringifiedValue, &DynSolType::Int(256))
82 }
83}
84
85impl Cheatcode for parseBytes32Call {
86 fn apply<FEN: FoundryEvmNetwork>(&self, _state: &mut Cheatcodes<FEN>) -> Result {
87 let Self { stringifiedValue } = self;
88 parse(stringifiedValue, &DynSolType::FixedBytes(32))
89 }
90}
91
92impl Cheatcode for parseBoolCall {
93 fn apply<FEN: FoundryEvmNetwork>(&self, _state: &mut Cheatcodes<FEN>) -> Result {
94 let Self { stringifiedValue } = self;
95 parse(stringifiedValue, &DynSolType::Bool)
96 }
97}
98
99impl Cheatcode for toLowercaseCall {
100 fn apply<FEN: FoundryEvmNetwork>(&self, _state: &mut Cheatcodes<FEN>) -> Result {
101 let Self { input } = self;
102 Ok(input.to_lowercase().abi_encode())
103 }
104}
105
106impl Cheatcode for toUppercaseCall {
107 fn apply<FEN: FoundryEvmNetwork>(&self, _state: &mut Cheatcodes<FEN>) -> Result {
108 let Self { input } = self;
109 Ok(input.to_uppercase().abi_encode())
110 }
111}
112
113impl Cheatcode for trimCall {
114 fn apply<FEN: FoundryEvmNetwork>(&self, _state: &mut Cheatcodes<FEN>) -> Result {
115 let Self { input } = self;
116 Ok(input.trim().abi_encode())
117 }
118}
119
120impl Cheatcode for replaceCall {
121 fn apply<FEN: FoundryEvmNetwork>(&self, _state: &mut Cheatcodes<FEN>) -> Result {
122 let Self { input, from, to } = self;
123 Ok(input.replace(from, to).abi_encode())
124 }
125}
126
127impl Cheatcode for splitCall {
128 fn apply<FEN: FoundryEvmNetwork>(&self, _state: &mut Cheatcodes<FEN>) -> Result {
129 let Self { input, delimiter } = self;
130 let parts: Vec<&str> = input.split(delimiter).collect();
131 Ok(parts.abi_encode())
132 }
133}
134
135impl Cheatcode for indexOfCall {
136 fn apply<FEN: FoundryEvmNetwork>(&self, _state: &mut Cheatcodes<FEN>) -> Result {
137 let Self { input, key } = self;
138 Ok(input.find(key).map(U256::from).unwrap_or(U256::MAX).abi_encode())
139 }
140}
141
142impl Cheatcode for containsCall {
143 fn apply<FEN: FoundryEvmNetwork>(&self, _state: &mut Cheatcodes<FEN>) -> Result {
144 let Self { subject, search } = self;
145 Ok(subject.contains(search).abi_encode())
146 }
147}
148
149pub(super) fn parse(s: &str, ty: &DynSolType) -> Result {
150 parse_value(s, ty).map(|v| v.abi_encode())
151}
152
153pub(super) fn parse_array<I, S>(values: I, ty: &DynSolType) -> Result
154where
155 I: IntoIterator<Item = S>,
156 S: AsRef<str>,
157{
158 let mut values = values.into_iter();
159 match values.next() {
160 Some(first) if !first.as_ref().is_empty() => std::iter::once(first)
161 .chain(values)
162 .map(|s| parse_value(s.as_ref(), ty))
163 .collect::<Result<Vec<_>, _>>()
164 .map(|vec| DynSolValue::Array(vec).abi_encode()),
165 _ => Ok("".abi_encode()),
167 }
168}
169
170pub(super) fn parse_value(s: &str, ty: &DynSolType) -> Result<DynSolValue> {
171 match ty.coerce_str(s) {
172 Ok(value) => Ok(value),
173 Err(e) => match parse_value_fallback(s, ty) {
174 Some(Ok(value)) => Ok(value),
175 Some(Err(e2)) => Err(fmt_err!("failed parsing {s:?} as type `{ty}`: {e2}")),
176 None => Err(fmt_err!("failed parsing {s:?} as type `{ty}`: {e}")),
177 },
178 }
179}
180
181fn parse_value_fallback(s: &str, ty: &DynSolType) -> Option<Result<DynSolValue, &'static str>> {
183 match ty {
184 DynSolType::Bool => {
185 let b = match s {
186 "1" => true,
187 "0" => false,
188 s if s.eq_ignore_ascii_case("true") => true,
189 s if s.eq_ignore_ascii_case("false") => false,
190 _ => return None,
191 };
192 return Some(Ok(DynSolValue::Bool(b)));
193 }
194 DynSolType::Int(_)
195 | DynSolType::Uint(_)
196 | DynSolType::FixedBytes(_)
197 | DynSolType::Bytes
198 if !s.starts_with("0x") && hex::check_raw(s) =>
199 {
200 return Some(Err("missing hex prefix (\"0x\") for hex string"));
201 }
202 _ => {}
203 }
204 None
205}