1use ethrex_common::Bytes;
2use ethrex_common::H256;
3use ethrex_common::utils::{decode_hex, keccak};
4use ethrex_common::{Address, H32, U256};
5use ethrex_l2_common::calldata::Value;
6use ethrex_rpc::clients::EthClientError;
7use ethrex_rpc::clients::eth::errors::CalldataEncodeError;
8
9use crate::address_to_word;
10
11#[derive(Debug, thiserror::Error)]
12pub enum CalldataDecodeError {
13 #[error("Failed to parse function signature: {0}")]
14 ParseError(String),
15 #[error("Invalid calldata. Tried to read more bytes than there are.")]
16 OutOfBounds,
17 #[error("Internal Calldata decoding error. This is most likely a bug")]
18 InternalError,
19}
20
21pub fn parse_signature(signature: &str) -> Result<(String, Vec<String>), CalldataEncodeError> {
22 let sig = signature.trim().trim_start_matches("function ");
23 let (name, params) = sig
24 .split_once('(')
25 .ok_or(CalldataEncodeError::ParseError(signature.to_owned()))?;
26 let params = params.rsplit_once(')').map_or(params, |(left, _)| left);
27
28 let mut splitted_params = Vec::new();
32 let mut current_param = String::new();
33 let mut parenthesis_depth = 0;
34
35 for ch in params.chars() {
36 match ch {
37 '(' => {
38 parenthesis_depth += 1;
39 current_param.push(ch);
40 }
41 ')' => {
42 parenthesis_depth -= 1;
43 current_param.push(ch);
44 }
45 ',' if parenthesis_depth == 0 => {
46 if !current_param.is_empty() {
47 splitted_params.push(current_param.trim().to_string());
48 current_param = String::new();
49 }
50 }
51 _ => current_param.push(ch),
52 }
53 }
54
55 if !current_param.is_empty() {
57 splitted_params.push(current_param.trim().to_string());
58 }
59
60 Ok((name.to_string(), splitted_params))
61}
62
63#[doc(hidden)]
64pub fn compute_function_selector(
68 name: &str,
69 params: &[String],
70) -> Result<H32, CalldataEncodeError> {
71 let normalized_signature = format!("{name}({})", params.join(","));
72 let hash = keccak(normalized_signature.as_bytes());
73
74 Ok(H32::from(&hash[..4].try_into().map_err(|_| {
75 CalldataEncodeError::ParseError(name.to_owned())
76 })?))
77}
78
79pub fn encode_calldata(signature: &str, values: &[Value]) -> Result<Vec<u8>, CalldataEncodeError> {
80 let (name, params) = parse_signature(signature)?;
81
82 let mut params = params;
85 if params.is_empty() {
86 params = vec![];
87 }
88
89 if params.len() != values.len() {
90 return Err(CalldataEncodeError::WrongArgumentLength(
91 signature.to_owned(),
92 ));
93 }
94
95 let function_selector = compute_function_selector(&name, ¶ms)?;
96 let calldata = encode_tuple(values)?;
97 let mut with_selector = function_selector.as_bytes().to_vec();
98
99 with_selector.extend_from_slice(&calldata);
100
101 Ok(with_selector)
102}
103
104pub fn decode_calldata(signature: &str, data: Bytes) -> Result<Vec<Value>, CalldataDecodeError> {
105 let (_, params) =
106 parse_signature(signature).map_err(|e| CalldataDecodeError::ParseError(e.to_string()))?;
107 let mut decoder = DecodeHelper::new(&data);
108 let datatype = DataType::Tuple(
109 params
110 .iter()
111 .map(|v| DataType::parse(v))
112 .collect::<Result<Vec<_>, _>>()?,
113 );
114 match datatype.decode(&mut decoder)? {
115 Value::Tuple(values) => Ok(values),
116 _ => Err(CalldataDecodeError::InternalError),
117 }
118}
119
120struct DecodeHelper<'a> {
121 buf: &'a [u8],
122 index: usize,
123}
124
125const SELECTOR_SIZE: usize = 4;
126
127impl<'a> DecodeHelper<'a> {
128 fn new(buf: &'a [u8]) -> Self {
129 DecodeHelper {
130 buf,
131 index: SELECTOR_SIZE,
132 }
133 }
134 fn consume(&mut self, n: usize) -> Result<&'a [u8], CalldataDecodeError> {
135 let data = self
136 .buf
137 .get(self.index..self.index + n)
138 .ok_or(CalldataDecodeError::OutOfBounds)?;
139 self.index += n;
140 Ok(data)
141 }
142 fn consume_u256(&mut self) -> Result<U256, CalldataDecodeError> {
143 Ok(U256::from_big_endian(self.consume(32)?))
144 }
145 fn start_reading_at(&self, offset: usize) -> Result<Self, CalldataDecodeError> {
146 let data = self
147 .buf
148 .get(self.index + offset..)
149 .ok_or(CalldataDecodeError::OutOfBounds)?;
150 Ok(DecodeHelper {
151 buf: data,
152 index: 0,
153 })
154 }
155}
156
157#[derive(Clone, Debug)]
158enum DataType {
159 Array(Box<DataType>),
160 FixedArray(usize, Box<DataType>),
161 Tuple(Vec<DataType>),
162 Bytes,
163 FixedBytes(usize),
164 Address,
165 Bool,
166 Uint,
167 Int,
168}
169
170impl DataType {
171 fn parse(param: &str) -> Result<Self, CalldataDecodeError> {
172 Ok(match param {
173 _ if param.ends_with("[]") => {
174 let inner = param
175 .strip_suffix("[]")
176 .ok_or(CalldataDecodeError::InternalError)?;
177 DataType::Array(Box::new(DataType::parse(inner)?))
178 }
179 _ if param.ends_with("]") => {
180 let mut n = String::new();
181 let mut iter = param.chars().rev().skip(1);
182 for c in iter.by_ref() {
183 if c.is_ascii_digit() {
184 n.insert(0, c);
185 } else {
186 if c != '[' {
187 return Err(CalldataDecodeError::ParseError(format!(
188 "expected ] but found {c}"
189 )));
190 }
191 break;
192 }
193 }
194 iter.next();
195 let inner: String = iter.collect::<String>().chars().rev().collect();
196 let n: usize = n.parse().map_err(|_| CalldataDecodeError::OutOfBounds)?;
197 DataType::FixedArray(n, Box::new(DataType::parse(&inner)?))
198 }
199 _ if param.ends_with(")") => {
200 let (_, inner) = parse_signature(param)
201 .map_err(|e| CalldataDecodeError::ParseError(e.to_string()))?;
202 DataType::Tuple(
203 inner
204 .iter()
205 .map(|v| DataType::parse(v))
206 .collect::<Result<Vec<_>, _>>()?,
207 )
208 }
209 "address" => DataType::Address,
210 "bool" => DataType::Bool,
211 "bytes" => DataType::Bytes,
212 _ if param.starts_with("bytes") => {
213 let n = param
214 .trim_start_matches("bytes")
215 .parse()
216 .map_err(|_| CalldataDecodeError::ParseError("invalid bytesN".to_string()))?;
217 DataType::FixedBytes(n)
218 }
219 _ if param.starts_with("uint") => DataType::Uint,
220 _ if param.starts_with("int") => DataType::Int,
221 _ => {
222 return Err(CalldataDecodeError::ParseError(format!(
223 "unknown type {param}"
224 )));
225 }
226 })
227 }
228 fn is_dynamic(&self) -> bool {
229 match self {
230 DataType::Array(_) => true,
231 DataType::Bytes => true,
232 DataType::FixedArray(_, inner) => inner.is_dynamic(),
233 DataType::Tuple(inner) => inner.iter().any(|t| t.is_dynamic()),
234 _ => false,
235 }
236 }
237 fn decode(&self, data: &mut DecodeHelper) -> Result<Value, CalldataDecodeError> {
238 Ok(match self {
239 DataType::Uint => Value::Uint(data.consume_u256()?),
240 DataType::Int => Value::Int(data.consume_u256()?),
241 DataType::Address => {
242 data.consume(32 - 20)?;
243 Value::Address(Address::from_slice(data.consume(20)?))
244 }
245 DataType::Bool => Value::Bool(!data.consume_u256()?.is_zero()),
246 DataType::FixedBytes(n) => Value::FixedBytes(
247 data.consume(32)?
248 .get(0..*n)
249 .ok_or(CalldataDecodeError::OutOfBounds)?
250 .to_vec()
251 .into(),
252 ),
253 DataType::Bytes => {
254 let n: usize = data
255 .consume_u256()?
256 .try_into()
257 .map_err(|_| CalldataDecodeError::OutOfBounds)?;
258 let size = if n.is_multiple_of(32) {
259 n
260 } else {
261 n.next_multiple_of(32)
262 };
263 Value::Bytes(
264 data.consume(size)?
265 .get(0..n)
266 .ok_or(CalldataDecodeError::OutOfBounds)?
267 .to_vec()
268 .into(),
269 )
270 }
271 DataType::FixedArray(n, inner_type) => {
272 let inner_type = *inner_type.clone();
273 let value = DataType::Tuple(vec![inner_type; *n]).decode(data)?;
274 match value {
275 Value::Tuple(inner) => Value::FixedArray(inner),
276 _ => return Err(CalldataDecodeError::InternalError),
277 }
278 }
279 DataType::Tuple(inner_types) => {
280 let mut values = Vec::new();
281 let start_reader = data.start_reading_at(0)?;
282 for inner_type in inner_types {
283 if inner_type.is_dynamic() {
284 let offset: usize = data
285 .consume_u256()?
286 .try_into()
287 .map_err(|_| CalldataDecodeError::OutOfBounds)?;
288 values
289 .push(inner_type.decode(&mut start_reader.start_reading_at(offset)?)?);
290 } else {
291 values.push(inner_type.decode(data)?);
292 }
293 }
294 Value::Tuple(values)
295 }
296 DataType::Array(inner_type) => {
297 let n: usize = data
298 .consume_u256()?
299 .try_into()
300 .map_err(|_| CalldataDecodeError::OutOfBounds)?;
301 let mut values = Vec::new();
302 for _ in 0..n {
303 values.push(inner_type.decode(data)?);
304 }
305 Value::Array(values)
306 }
307 })
308 }
309}
310
311pub fn encode_tuple(values: &[Value]) -> Result<Vec<u8>, CalldataEncodeError> {
319 let mut current_offset = 0;
320 let mut current_dynamic_offset = 0;
321 for value in values {
322 current_dynamic_offset += static_offset_value(value);
323 }
324
325 let mut ret = vec![0; current_dynamic_offset];
326
327 for value in values {
328 match value {
329 Value::Address(h160) => {
330 write_u256(&mut ret, address_to_word(*h160), current_offset)?;
331 }
332 Value::Uint(u256) => {
333 write_u256(&mut ret, *u256, current_offset)?;
334 }
335 Value::Int(u256) => {
336 write_u256(&mut ret, *u256, current_offset)?;
337 }
338 Value::Bool(boolean) => {
339 write_u256(&mut ret, U256::from(u8::from(*boolean)), current_offset)?;
340 }
341 Value::Bytes(bytes) => {
342 write_u256(&mut ret, U256::from(current_dynamic_offset), current_offset)?;
343
344 let bytes_encoding = encode_bytes(bytes);
345 ret.extend_from_slice(&bytes_encoding);
346 current_dynamic_offset += bytes_encoding.len();
347 }
348 Value::String(string_value) => {
349 write_u256(&mut ret, U256::from(current_dynamic_offset), current_offset)?;
350
351 let utf8_encoded = Bytes::copy_from_slice(string_value.as_bytes());
352 let bytes_encoding = encode_bytes(&utf8_encoded);
353 ret.extend_from_slice(&bytes_encoding);
354 current_dynamic_offset += bytes_encoding.len();
355 }
356 Value::Array(array_values) => {
357 write_u256(&mut ret, U256::from(current_dynamic_offset), current_offset)?;
358
359 let array_encoding = encode_array(array_values)?;
360 ret.extend_from_slice(&array_encoding);
361 current_dynamic_offset += array_encoding.len();
362 }
363 Value::Tuple(tuple_values) => {
364 if !is_dynamic(value) {
365 let tuple_encoding = encode_tuple(tuple_values)?;
366 copy_into(
367 &mut ret,
368 &tuple_encoding,
369 current_offset,
370 tuple_encoding.len(),
371 )?;
372 } else {
373 write_u256(&mut ret, U256::from(current_dynamic_offset), current_offset)?;
374
375 let tuple_encoding = encode_tuple(tuple_values)?;
376 ret.extend_from_slice(&tuple_encoding);
377 current_dynamic_offset += tuple_encoding.len();
378 }
379 }
380 Value::FixedArray(fixed_array_values) => {
381 if !is_dynamic(value) {
382 let fixed_array_encoding = encode_tuple(fixed_array_values)?;
383 copy_into(
384 &mut ret,
385 &fixed_array_encoding,
386 current_offset,
387 fixed_array_encoding.len(),
388 )?;
389 } else {
390 write_u256(&mut ret, U256::from(current_dynamic_offset), current_offset)?;
391
392 let tuple_encoding = encode_tuple(fixed_array_values)?;
393 ret.extend_from_slice(&tuple_encoding);
394 current_dynamic_offset += tuple_encoding.len();
395 }
396 }
397 Value::FixedBytes(bytes) => {
398 let mut bytes = bytes.to_vec();
399 bytes.resize(32, 0);
400 copy_into(&mut ret, &bytes, current_offset, 32)?;
401 }
402 }
403
404 current_offset += static_offset_value(value);
405 }
406
407 Ok(ret)
408}
409
410fn write_u256(values: &mut [u8], number: U256, offset: usize) -> Result<(), CalldataEncodeError> {
411 let to_copy = number.to_big_endian();
412 copy_into(values, &to_copy, offset, 32)?;
413
414 Ok(())
415}
416
417fn static_offset_value(value: &Value) -> usize {
422 let mut ret = 0;
423
424 match value {
425 Value::Address(_)
426 | Value::Uint(_)
427 | Value::Int(_)
428 | Value::Bool(_)
429 | Value::Bytes(_)
430 | Value::String(_)
431 | Value::Array(_)
432 | Value::FixedBytes(_) => ret += 32,
433 Value::Tuple(vec) => {
434 if is_dynamic(value) {
435 ret += 32;
436 } else {
437 for element in vec {
438 ret += static_offset_value(element);
441 }
442 }
443 }
444 Value::FixedArray(vec) => {
445 if is_dynamic(value) {
446 ret += 32;
447 } else {
448 for element in vec {
449 ret += static_offset_value(element);
452 }
453 }
454 }
455 }
456
457 ret
458}
459
460fn is_dynamic(value: &Value) -> bool {
461 match value {
462 Value::Bytes(_) | Value::String(_) | Value::Array(_) => true,
463 Value::Tuple(vec) => vec.iter().any(is_dynamic),
464 Value::FixedArray(vec) => {
465 if let Some(first_elem) = vec.first() {
466 is_dynamic(first_elem)
467 } else {
468 false
469 }
470 }
471 _ => false,
472 }
473}
474
475fn encode_array(values: &[Value]) -> Result<Vec<u8>, CalldataEncodeError> {
476 let mut ret = vec![];
477 let to_copy = U256::from(values.len()).to_big_endian();
478 ret.extend_from_slice(&to_copy);
479
480 let tuple_encoding = encode_tuple(values)?;
481 ret.extend_from_slice(&tuple_encoding);
482
483 Ok(ret)
484}
485
486fn encode_bytes(values: &Bytes) -> Vec<u8> {
487 let mut ret = vec![];
488
489 let padding = 32 - (values.len() % 32);
491 let mut padded_bytes = values.to_vec();
492 if padding != 32 {
493 padded_bytes.extend_from_slice(&vec![0; padding]);
494 }
495
496 let to_copy = U256::from(values.len()).to_big_endian(); ret.extend_from_slice(&to_copy);
499 ret.extend_from_slice(&padded_bytes);
500
501 ret
502}
503
504fn copy_into(
505 values: &mut [u8],
506 to_copy: &[u8],
507 offset: usize,
508 size: usize,
509) -> Result<(), CalldataEncodeError> {
510 let to_copy_slice = to_copy
511 .get(..size)
512 .ok_or(CalldataEncodeError::InternalError)?;
513
514 values
515 .get_mut(offset..(size + offset))
516 .ok_or(CalldataEncodeError::InternalError)?
517 .copy_from_slice(to_copy_slice);
518
519 Ok(())
520}
521
522#[allow(clippy::indexing_slicing)]
523pub fn from_hex_string_to_h256_array(hex_string: &str) -> Result<Vec<H256>, EthClientError> {
524 let bytes = decode_hex(hex_string)
525 .map_err(|_| EthClientError::Custom("Invalid hex string".to_owned()))?;
526
527 if bytes.len() < 64 {
532 return Err(EthClientError::Custom("Response too short".to_owned()));
533 }
534
535 let offset = usize::try_from(U256::from_big_endian(&bytes[0..32]))
537 .map_err(|_| EthClientError::Custom("ABI offset overflows usize".to_owned()))?;
538
539 let length = usize::try_from(U256::from_big_endian(&bytes[offset..offset + 32]))
541 .map_err(|_| EthClientError::Custom("ABI array length overflows usize".to_owned()))?;
542
543 let data_start = offset + 32;
545 let data_end = data_start + (length * 32);
546
547 if data_end > bytes.len() {
548 return Err(EthClientError::Custom("Invalid array length".to_owned()));
549 }
550
551 bytes[data_start..data_end]
553 .chunks_exact(32)
554 .map(|chunk| Ok(H256::from_slice(chunk)))
555 .collect()
556}