1use crate::{DynSolValue, DynToken, Error, Result, SolType, Specifier, Word};
2use alloc::{borrow::Cow, boxed::Box, string::String, vec::Vec};
3use alloy_primitives::{
4 try_vec,
5 utils::{box_try_new, vec_try_with_capacity},
6};
7use alloy_sol_types::{abi::Decoder, sol_data};
8use core::{fmt, iter::zip, num::NonZeroUsize, str::FromStr};
9use parser::TypeSpecifier;
10
11#[cfg(feature = "eip712")]
12macro_rules! as_tuple {
13 ($ty:ident $t:tt) => {
14 $ty::Tuple($t) | $ty::CustomStruct { tuple: $t, .. }
15 };
16}
17#[cfg(not(feature = "eip712"))]
18macro_rules! as_tuple {
19 ($ty:ident $t:tt) => {
20 $ty::Tuple($t)
21 };
22}
23pub(crate) use as_tuple;
24
25#[derive(Clone, Debug, PartialEq, Eq, Hash)]
80pub enum DynSolType {
81 Bool,
83 Int(usize),
85 Uint(usize),
87 FixedBytes(usize),
89 Address,
91 Function,
93
94 Bytes,
96 String,
98
99 Array(Box<DynSolType>),
101 FixedArray(Box<DynSolType>, usize),
103 Tuple(Vec<DynSolType>),
105
106 #[cfg(feature = "eip712")]
108 CustomStruct {
109 name: String,
111 prop_names: Vec<String>,
113 tuple: Vec<DynSolType>,
115 },
116}
117
118impl fmt::Display for DynSolType {
119 #[inline]
120 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
121 f.write_str(&self.sol_type_name())
122 }
123}
124
125impl FromStr for DynSolType {
126 type Err = Error;
127
128 #[inline]
129 fn from_str(s: &str) -> Result<Self, Self::Err> {
130 Self::parse(s)
131 }
132}
133
134impl DynSolType {
135 #[inline]
153 pub fn parse(s: &str) -> Result<Self> {
154 TypeSpecifier::parse(s).map_err(Error::TypeParser).and_then(|t| t.resolve())
155 }
156
157 pub fn nesting_depth(&self) -> usize {
160 match self {
161 Self::Bool
162 | Self::Int(_)
163 | Self::Uint(_)
164 | Self::FixedBytes(_)
165 | Self::Address
166 | Self::Function
167 | Self::Bytes
168 | Self::String => 0,
169 Self::Array(contents) | Self::FixedArray(contents, _) => 1 + contents.nesting_depth(),
170 as_tuple!(Self tuple) => 1 + tuple.iter().map(Self::nesting_depth).max().unwrap_or(0),
171 }
172 }
173
174 #[inline]
176 pub fn as_tuple(&self) -> Option<&[Self]> {
177 match self {
178 Self::Tuple(t) => Some(t),
179 _ => None,
180 }
181 }
182
183 #[inline]
185 #[allow(clippy::missing_const_for_fn)]
186 pub fn as_custom_struct(&self) -> Option<(&str, &[String], &[Self])> {
187 match self {
188 #[cfg(feature = "eip712")]
189 Self::CustomStruct { name, prop_names, tuple } => Some((name, prop_names, tuple)),
190 _ => None,
191 }
192 }
193
194 #[inline]
196 #[allow(clippy::missing_const_for_fn)]
197 pub fn has_custom_struct(&self) -> bool {
198 #[cfg(feature = "eip712")]
199 {
200 match self {
201 Self::CustomStruct { .. } => true,
202 Self::Array(t) => t.has_custom_struct(),
203 Self::FixedArray(t, _) => t.has_custom_struct(),
204 Self::Tuple(t) => t.iter().any(Self::has_custom_struct),
205 _ => false,
206 }
207 }
208 #[cfg(not(feature = "eip712"))]
209 {
210 false
211 }
212 }
213
214 #[inline]
218 pub fn matches_many(types: &[Self], values: &[DynSolValue]) -> bool {
219 types.len() == values.len() && zip(types, values).all(|(t, v)| t.matches(v))
220 }
221
222 pub fn matches(&self, value: &DynSolValue) -> bool {
228 match self {
229 Self::Bool => matches!(value, DynSolValue::Bool(_)),
230 Self::Int(size) => matches!(value, DynSolValue::Int(_, s) if s == size),
231 Self::Uint(size) => matches!(value, DynSolValue::Uint(_, s) if s == size),
232 Self::FixedBytes(size) => matches!(value, DynSolValue::FixedBytes(_, s) if s == size),
233 Self::Address => matches!(value, DynSolValue::Address(_)),
234 Self::Function => matches!(value, DynSolValue::Function(_)),
235 Self::Bytes => matches!(value, DynSolValue::Bytes(_)),
236 Self::String => matches!(value, DynSolValue::String(_)),
237 Self::Array(t) => {
238 matches!(value, DynSolValue::Array(v) if v.iter().all(|v| t.matches(v)))
239 }
240 Self::FixedArray(t, size) => matches!(
241 value,
242 DynSolValue::FixedArray(v) if v.len() == *size && v.iter().all(|v| t.matches(v))
243 ),
244 Self::Tuple(types) => {
245 matches!(value, as_tuple!(DynSolValue tuple) if zip(types, tuple).all(|(t, v)| t.matches(v)))
246 }
247 #[cfg(feature = "eip712")]
248 Self::CustomStruct { name: _, prop_names, tuple } => {
249 if let DynSolValue::CustomStruct { name: _, prop_names: p, tuple: t } = value {
250 prop_names.len() == tuple.len()
252 && prop_names.len() == p.len()
253 && tuple.len() == t.len()
254 && zip(tuple, t).all(|(a, b)| a.matches(b))
255 } else if let DynSolValue::Tuple(v) = value {
256 zip(v, tuple).all(|(v, t)| t.matches(v))
257 } else {
258 false
259 }
260 }
261 }
262 }
263
264 #[allow(clippy::unnecessary_to_owned)] pub fn detokenize(&self, token: DynToken<'_>) -> Result<DynSolValue> {
268 match (self, token) {
269 (Self::Bool, DynToken::Word(word)) => {
270 Ok(DynSolValue::Bool(sol_data::Bool::detokenize(word.into())))
271 }
272
273 (Self::Int(size), DynToken::Word(word)) => {
275 Ok(DynSolValue::Int(sol_data::Int::<256>::detokenize(word.into()), *size))
276 }
277
278 (Self::Uint(size), DynToken::Word(word)) => {
279 Ok(DynSolValue::Uint(sol_data::Uint::<256>::detokenize(word.into()), *size))
280 }
281
282 (Self::FixedBytes(size), DynToken::Word(word)) => Ok(DynSolValue::FixedBytes(
283 sol_data::FixedBytes::<32>::detokenize(word.into()),
284 *size,
285 )),
286
287 (Self::Address, DynToken::Word(word)) => {
288 Ok(DynSolValue::Address(sol_data::Address::detokenize(word.into())))
289 }
290
291 (Self::Function, DynToken::Word(word)) => {
292 Ok(DynSolValue::Function(sol_data::Function::detokenize(word.into())))
293 }
294
295 (Self::Bytes, DynToken::PackedSeq(buf)) => Ok(DynSolValue::Bytes(buf.to_vec())),
296
297 (Self::String, DynToken::PackedSeq(buf)) => {
298 Ok(DynSolValue::String(sol_data::String::detokenize(buf.into())))
299 }
300
301 (Self::Array(t), DynToken::DynSeq { contents, .. }) => {
302 t.detokenize_array(contents.into_owned()).map(DynSolValue::Array)
303 }
304
305 (Self::FixedArray(t, size), DynToken::FixedSeq(tokens, _)) => {
306 if *size != tokens.len() {
307 return Err(crate::Error::custom(
308 "array length mismatch on dynamic detokenization",
309 ));
310 }
311 t.detokenize_array(tokens.into_owned()).map(DynSolValue::FixedArray)
312 }
313
314 (Self::Tuple(types), DynToken::FixedSeq(tokens, _)) => {
315 if types.len() != tokens.len() {
316 return Err(crate::Error::custom(
317 "tuple length mismatch on dynamic detokenization",
318 ));
319 }
320 Self::detokenize_many(types, tokens.into_owned()).map(DynSolValue::Tuple)
321 }
322
323 #[cfg(feature = "eip712")]
324 (Self::CustomStruct { name, tuple, prop_names }, DynToken::FixedSeq(tokens, len)) => {
325 if len != tokens.len() || len != tuple.len() {
326 return Err(crate::Error::custom(
327 "custom length mismatch on dynamic detokenization",
328 ));
329 }
330 Self::detokenize_many(tuple, tokens.into_owned()).map(|tuple| {
331 DynSolValue::CustomStruct {
332 name: name.clone(),
333 prop_names: prop_names.clone(),
334 tuple,
335 }
336 })
337 }
338
339 _ => Err(crate::Error::custom("mismatched types on dynamic detokenization")),
340 }
341 }
342
343 fn detokenize_array(&self, tokens: Vec<DynToken<'_>>) -> Result<Vec<DynSolValue>> {
344 let mut values = vec_try_with_capacity(tokens.len())?;
345 for token in tokens {
346 values.push(self.detokenize(token)?);
347 }
348 Ok(values)
349 }
350
351 fn detokenize_many(types: &[Self], tokens: Vec<DynToken<'_>>) -> Result<Vec<DynSolValue>> {
352 assert_eq!(types.len(), tokens.len());
353 let mut values = vec_try_with_capacity(tokens.len())?;
354 for (ty, token) in zip(types, tokens) {
355 values.push(ty.detokenize(token)?);
356 }
357 Ok(values)
358 }
359
360 #[inline]
361 #[allow(clippy::missing_const_for_fn)]
362 fn sol_type_name_simple(&self) -> Option<&'static str> {
363 match self {
364 Self::Address => Some("address"),
365 Self::Function => Some("function"),
366 Self::Bool => Some("bool"),
367 Self::Bytes => Some("bytes"),
368 Self::String => Some("string"),
369 _ => None,
370 }
371 }
372
373 #[inline]
374 fn sol_type_name_raw(&self, out: &mut String) {
375 match self {
376 Self::Address | Self::Function | Self::Bool | Self::Bytes | Self::String => {
377 out.push_str(unsafe { self.sol_type_name_simple().unwrap_unchecked() });
378 }
379
380 Self::FixedBytes(size) | Self::Int(size) | Self::Uint(size) => {
381 let prefix = match self {
382 Self::FixedBytes(..) => "bytes",
383 Self::Int(..) => "int",
384 Self::Uint(..) => "uint",
385 _ => unreachable!(),
386 };
387 out.push_str(prefix);
388 out.push_str(itoa::Buffer::new().format(*size));
389 }
390
391 as_tuple!(Self tuple) => {
392 out.push('(');
393 for (i, val) in tuple.iter().enumerate() {
394 if i > 0 {
395 out.push(',');
396 }
397 val.sol_type_name_raw(out);
398 }
399 if tuple.len() == 1 {
400 out.push(',');
401 }
402 out.push(')');
403 }
404 Self::Array(t) => {
405 t.sol_type_name_raw(out);
406 out.push_str("[]");
407 }
408 Self::FixedArray(t, len) => {
409 t.sol_type_name_raw(out);
410 out.push('[');
411 out.push_str(itoa::Buffer::new().format(*len));
412 out.push(']');
413 }
414 }
415 }
416
417 fn sol_type_name_capacity(&self) -> usize {
423 match self {
424 | Self::Address | Self::Function | Self::Bool | Self::Bytes | Self::String | Self::FixedBytes(_) | Self::Int(_) | Self::Uint(_) => 8,
433
434 | Self::Array(t) | Self::FixedArray(t, _) => t.sol_type_name_capacity() + 8,
437
438 as_tuple!(Self tuple) => tuple.iter().map(Self::sol_type_name_capacity).sum::<usize>() + 8,
440 }
441 }
442
443 pub fn sol_type_name(&self) -> Cow<'static, str> {
447 if let Some(s) = self.sol_type_name_simple() {
448 Cow::Borrowed(s)
449 } else {
450 let mut s = String::with_capacity(self.sol_type_name_capacity());
451 self.sol_type_name_raw(&mut s);
452 Cow::Owned(s)
453 }
454 }
455
456 #[inline]
461 #[allow(clippy::inherent_to_string_shadow_display)]
462 pub fn to_string(&self) -> String {
463 self.sol_type_name().into_owned()
464 }
465
466 fn empty_dyn_token<'a>(&self) -> Result<DynToken<'a>> {
473 Ok(match self {
474 Self::Address
475 | Self::Function
476 | Self::Bool
477 | Self::FixedBytes(_)
478 | Self::Int(_)
479 | Self::Uint(_) => DynToken::Word(Word::ZERO),
480
481 Self::Bytes | Self::String => DynToken::PackedSeq(&[]),
482
483 Self::Array(t) => DynToken::DynSeq {
484 contents: Default::default(),
485 template: Some(box_try_new(t.empty_dyn_token()?)?),
486 },
487 &Self::FixedArray(ref t, size) => {
488 DynToken::FixedSeq(try_vec![t.empty_dyn_token()?; size]?.into(), size)
489 }
490 as_tuple!(Self tuple) => {
491 let mut tokens = vec_try_with_capacity(tuple.len())?;
492 for ty in tuple {
493 tokens.push(ty.empty_dyn_token()?);
494 }
495 DynToken::FixedSeq(tokens.into(), tuple.len())
496 }
497 })
498 }
499
500 pub(crate) fn decode_event_topic(&self, topic: Word) -> DynSolValue {
502 match self {
503 Self::Address
504 | Self::Function
505 | Self::Bool
506 | Self::FixedBytes(_)
507 | Self::Int(_)
508 | Self::Uint(_) => self.detokenize(DynToken::Word(topic)).unwrap(),
509 _ => DynSolValue::FixedBytes(topic, 32),
510 }
511 }
512
513 #[inline]
519 #[cfg_attr(debug_assertions, track_caller)]
520 pub fn abi_decode(&self, data: &[u8]) -> Result<DynSolValue> {
521 self.abi_decode_inner(&mut Decoder::new(data), DynToken::decode_single_populate)
522 }
523
524 #[inline]
545 #[cfg_attr(debug_assertions, track_caller)]
546 pub fn abi_decode_params(&self, data: &[u8]) -> Result<DynSolValue> {
547 match self {
548 Self::Tuple(_) => self.abi_decode_sequence(data),
549 _ => self.abi_decode(data),
550 }
551 }
552
553 #[inline]
556 #[cfg_attr(debug_assertions, track_caller)]
557 pub fn abi_decode_sequence(&self, data: &[u8]) -> Result<DynSolValue> {
558 self.abi_decode_inner(&mut Decoder::new(data), DynToken::decode_sequence_populate)
559 }
560
561 pub fn is_dynamic(&self) -> bool {
563 match self {
564 Self::Address
565 | Self::Function
566 | Self::Bool
567 | Self::Uint(..)
568 | Self::Int(..)
569 | Self::FixedBytes(..) => false,
570 Self::Bytes | Self::String | Self::Array(_) => true,
571 Self::Tuple(tuple) => tuple.iter().any(Self::is_dynamic),
572 Self::FixedArray(inner, _) => inner.is_dynamic(),
573 #[cfg(feature = "eip712")]
574 Self::CustomStruct { tuple, .. } => tuple.iter().any(Self::is_dynamic),
575 }
576 }
577
578 pub fn minimum_words(&self) -> usize {
581 match self {
582 Self::Bool |
584 Self::Int(_) |
585 Self::Uint(_) |
586 Self::FixedBytes(_) |
587 Self::Address |
588 Self::Function |
589 Self::Bytes |
591 Self::String |
592 Self::Array(_) => 1,
593 Self::FixedArray(v, size) => size * v.minimum_words(),
595 Self::Tuple(tuple) => tuple.iter().map(|ty| ty.minimum_words()).sum(),
596 #[cfg(feature = "eip712")]
597 Self::CustomStruct { tuple, ..} => tuple.iter().map(|ty| ty.minimum_words()).sum(),
598 }
599 }
600
601 #[inline]
602 #[cfg_attr(debug_assertions, track_caller)]
603 pub(crate) fn abi_decode_inner<'d, F>(
604 &self,
605 decoder: &mut Decoder<'d>,
606 f: F,
607 ) -> Result<DynSolValue>
608 where
609 F: FnOnce(&mut DynToken<'d>, &mut Decoder<'d>) -> Result<()>,
610 {
611 if self.is_zst() {
612 return Ok(self.zero_sized_value().expect("checked"));
613 }
614
615 if decoder.remaining_words() < self.minimum_words() {
616 return Err(Error::SolTypes(alloy_sol_types::Error::Overrun));
617 }
618
619 let mut token = self.empty_dyn_token()?;
620 f(&mut token, decoder)?;
621 let value = self.detokenize(token).expect("invalid empty_dyn_token");
622 debug_assert!(
623 self.matches(&value),
624 "decoded value does not match type:\n type: {self:?}\n value: {value:?}"
625 );
626 Ok(value)
627 }
628
629 #[inline]
631 pub(crate) fn array_wrap(self, size: Option<NonZeroUsize>) -> Self {
632 match size {
633 Some(size) => Self::FixedArray(Box::new(self), size.get()),
634 None => Self::Array(Box::new(self)),
635 }
636 }
637
638 #[inline]
640 pub(crate) fn array_wrap_from_iter(
641 self,
642 iter: impl IntoIterator<Item = Option<NonZeroUsize>>,
643 ) -> Self {
644 iter.into_iter().fold(self, Self::array_wrap)
645 }
646
647 #[inline]
649 pub fn is_zst(&self) -> bool {
650 match self {
651 Self::Array(inner) => inner.is_zst(),
652 Self::FixedArray(inner, size) => *size == 0 || inner.is_zst(),
653 Self::Tuple(inner) => inner.is_empty() || inner.iter().all(|t| t.is_zst()),
654 _ => false,
655 }
656 }
657
658 #[inline]
659 const fn zero_sized_value(&self) -> Option<DynSolValue> {
660 match self {
661 Self::Array(_) => Some(DynSolValue::Array(vec![])),
662 Self::FixedArray(_, _) => Some(DynSolValue::FixedArray(vec![])),
663 Self::Tuple(_) => Some(DynSolValue::Tuple(vec![])),
664 _ => None,
665 }
666 }
667}
668
669#[cfg(test)]
670mod tests {
671 use super::*;
672 use alloc::string::ToString;
673 use alloy_primitives::{Address, hex};
674
675 #[test]
676 fn dynamically_encodes() {
677 let word1 =
678 "0000000000000000000000000101010101010101010101010101010101010101".parse().unwrap();
679 let word2 =
680 "0000000000000000000000000202020202020202020202020202020202020202".parse().unwrap();
681
682 let val = DynSolValue::Address(Address::repeat_byte(0x01));
683 let token = val.tokenize();
684 assert_eq!(token, DynToken::from(word1));
685
686 let val = DynSolValue::FixedArray(vec![
687 Address::repeat_byte(0x01).into(),
688 Address::repeat_byte(0x02).into(),
689 ]);
690
691 let token = val.tokenize();
692 assert_eq!(
693 token,
694 DynToken::FixedSeq(vec![DynToken::Word(word1), DynToken::Word(word2)].into(), 2)
695 );
696 let mut enc = crate::Encoder::default();
697 DynSolValue::encode_seq_to(val.as_fixed_seq().unwrap(), &mut enc);
698 assert_eq!(enc.finish(), vec![word1, word2]);
699 }
700
701 macro_rules! encoder_tests {
703 ($($name:ident($ty:literal, $encoded:literal)),* $(,)?) => {$(
704 #[test]
705 fn $name() {
706 encoder_test($ty, &hex!($encoded));
707 }
708 )*};
709 }
710
711 fn encoder_test(s: &str, encoded: &[u8]) {
712 let ty: DynSolType = s.parse().expect("parsing failed");
713 assert_eq!(ty.sol_type_name(), s, "type names are not the same");
714
715 let value = ty.abi_decode_params(encoded).expect("decoding failed");
716 if let Some(value_name) = value.sol_type_name() {
717 assert_eq!(value_name, s, "value names are not the same");
718 }
719
720 let mut len = encoded.len();
726 if value.as_tuple().is_some() && value.is_dynamic() {
727 len += 32;
728 }
729 assert_eq!(value.total_words() * 32, len, "dyn_tuple={}", len != encoded.len());
730
731 let re_encoded = value.abi_encode_params();
732 assert!(
733 re_encoded == encoded,
734 "
735 type: {ty}
736 value: {value:?}
737re-enc: {re_enc}
738 enc: {encoded}",
739 re_enc = hex::encode(re_encoded),
740 encoded = hex::encode(encoded),
741 );
742 }
743
744 encoder_tests! {
745 address("address", "0000000000000000000000001111111111111111111111111111111111111111"),
746
747 dynamic_array_of_addresses("address[]", "
748 0000000000000000000000000000000000000000000000000000000000000020
749 0000000000000000000000000000000000000000000000000000000000000002
750 0000000000000000000000001111111111111111111111111111111111111111
751 0000000000000000000000002222222222222222222222222222222222222222
752 "),
753
754 fixed_array_of_addresses("address[2]", "
755 0000000000000000000000001111111111111111111111111111111111111111
756 0000000000000000000000002222222222222222222222222222222222222222
757 "),
758
759 two_addresses("(address,address)", "
760 0000000000000000000000001111111111111111111111111111111111111111
761 0000000000000000000000002222222222222222222222222222222222222222
762 "),
763
764 fixed_array_of_dynamic_arrays_of_addresses("address[][2]", "
765 0000000000000000000000000000000000000000000000000000000000000020
766 0000000000000000000000000000000000000000000000000000000000000040
767 00000000000000000000000000000000000000000000000000000000000000a0
768 0000000000000000000000000000000000000000000000000000000000000002
769 0000000000000000000000001111111111111111111111111111111111111111
770 0000000000000000000000002222222222222222222222222222222222222222
771 0000000000000000000000000000000000000000000000000000000000000002
772 0000000000000000000000003333333333333333333333333333333333333333
773 0000000000000000000000004444444444444444444444444444444444444444
774 "),
775
776 dynamic_array_of_fixed_arrays_of_addresses("address[2][]", "
777 0000000000000000000000000000000000000000000000000000000000000020
778 0000000000000000000000000000000000000000000000000000000000000002
779 0000000000000000000000001111111111111111111111111111111111111111
780 0000000000000000000000002222222222222222222222222222222222222222
781 0000000000000000000000003333333333333333333333333333333333333333
782 0000000000000000000000004444444444444444444444444444444444444444
783 "),
784
785 dynamic_array_of_dynamic_arrays("address[][]", "
786 0000000000000000000000000000000000000000000000000000000000000020
787 0000000000000000000000000000000000000000000000000000000000000002
788 0000000000000000000000000000000000000000000000000000000000000040
789 0000000000000000000000000000000000000000000000000000000000000080
790 0000000000000000000000000000000000000000000000000000000000000001
791 0000000000000000000000001111111111111111111111111111111111111111
792 0000000000000000000000000000000000000000000000000000000000000001
793 0000000000000000000000002222222222222222222222222222222222222222
794 "),
795
796 dynamic_array_of_dynamic_arrays2("address[][]", "
797 0000000000000000000000000000000000000000000000000000000000000020
798 0000000000000000000000000000000000000000000000000000000000000002
799 0000000000000000000000000000000000000000000000000000000000000040
800 00000000000000000000000000000000000000000000000000000000000000a0
801 0000000000000000000000000000000000000000000000000000000000000002
802 0000000000000000000000001111111111111111111111111111111111111111
803 0000000000000000000000002222222222222222222222222222222222222222
804 0000000000000000000000000000000000000000000000000000000000000002
805 0000000000000000000000003333333333333333333333333333333333333333
806 0000000000000000000000004444444444444444444444444444444444444444
807 "),
808
809 fixed_array_of_fixed_arrays("address[2][2]", "
810 0000000000000000000000001111111111111111111111111111111111111111
811 0000000000000000000000002222222222222222222222222222222222222222
812 0000000000000000000000003333333333333333333333333333333333333333
813 0000000000000000000000004444444444444444444444444444444444444444
814 "),
815
816 fixed_array_of_static_tuples_followed_by_dynamic_type("((uint256,uint256,address)[2],string)", "
817 0000000000000000000000000000000000000000000000000000000005930cc5
818 0000000000000000000000000000000000000000000000000000000015002967
819 0000000000000000000000004444444444444444444444444444444444444444
820 000000000000000000000000000000000000000000000000000000000000307b
821 00000000000000000000000000000000000000000000000000000000000001c3
822 0000000000000000000000002222222222222222222222222222222222222222
823 00000000000000000000000000000000000000000000000000000000000000e0
824 0000000000000000000000000000000000000000000000000000000000000009
825 6761766f66796f726b0000000000000000000000000000000000000000000000
826 "),
827
828 empty_array("address[]", "
829 0000000000000000000000000000000000000000000000000000000000000020
830 0000000000000000000000000000000000000000000000000000000000000000
831 "),
832
833 empty_array_2("(address[],address[])", "
834 0000000000000000000000000000000000000000000000000000000000000040
835 0000000000000000000000000000000000000000000000000000000000000060
836 0000000000000000000000000000000000000000000000000000000000000000
837 0000000000000000000000000000000000000000000000000000000000000000
838 "),
839
840 empty_array_3("(address[][],address[][])", "
842 0000000000000000000000000000000000000000000000000000000000000040
843 00000000000000000000000000000000000000000000000000000000000000a0
844 0000000000000000000000000000000000000000000000000000000000000001
845 0000000000000000000000000000000000000000000000000000000000000020
846 0000000000000000000000000000000000000000000000000000000000000000
847 0000000000000000000000000000000000000000000000000000000000000001
848 0000000000000000000000000000000000000000000000000000000000000020
849 0000000000000000000000000000000000000000000000000000000000000000
850 "),
851
852 fixed_bytes("bytes2", "1234000000000000000000000000000000000000000000000000000000000000"),
853
854 string("string", "
855 0000000000000000000000000000000000000000000000000000000000000020
856 0000000000000000000000000000000000000000000000000000000000000009
857 6761766f66796f726b0000000000000000000000000000000000000000000000
858 "),
859
860 bytes("bytes", "
861 0000000000000000000000000000000000000000000000000000000000000020
862 0000000000000000000000000000000000000000000000000000000000000002
863 1234000000000000000000000000000000000000000000000000000000000000
864 "),
865
866 bytes_2("bytes", "
867 0000000000000000000000000000000000000000000000000000000000000020
868 000000000000000000000000000000000000000000000000000000000000001f
869 1000000000000000000000000000000000000000000000000000000000000200
870 "),
871
872 bytes_3("bytes", "
873 0000000000000000000000000000000000000000000000000000000000000020
874 0000000000000000000000000000000000000000000000000000000000000040
875 1000000000000000000000000000000000000000000000000000000000000000
876 1000000000000000000000000000000000000000000000000000000000000000
877 "),
878
879 two_bytes("(bytes,bytes)", "
880 0000000000000000000000000000000000000000000000000000000000000040
881 0000000000000000000000000000000000000000000000000000000000000080
882 000000000000000000000000000000000000000000000000000000000000001f
883 1000000000000000000000000000000000000000000000000000000000000200
884 0000000000000000000000000000000000000000000000000000000000000020
885 0010000000000000000000000000000000000000000000000000000000000002
886 "),
887
888 uint("uint256", "0000000000000000000000000000000000000000000000000000000000000004"),
889
890 int("int256", "0000000000000000000000000000000000000000000000000000000000000004"),
891
892 bool("bool", "0000000000000000000000000000000000000000000000000000000000000001"),
893
894 bool2("bool", "0000000000000000000000000000000000000000000000000000000000000000"),
895
896 comprehensive_test("(uint8,bytes,uint8,bytes)", "
897 0000000000000000000000000000000000000000000000000000000000000005
898 0000000000000000000000000000000000000000000000000000000000000080
899 0000000000000000000000000000000000000000000000000000000000000003
900 00000000000000000000000000000000000000000000000000000000000000e0
901 0000000000000000000000000000000000000000000000000000000000000040
902 131a3afc00d1b1e3461b955e53fc866dcf303b3eb9f4c16f89e388930f48134b
903 131a3afc00d1b1e3461b955e53fc866dcf303b3eb9f4c16f89e388930f48134b
904 0000000000000000000000000000000000000000000000000000000000000040
905 131a3afc00d1b1e3461b955e53fc866dcf303b3eb9f4c16f89e388930f48134b
906 131a3afc00d1b1e3461b955e53fc866dcf303b3eb9f4c16f89e388930f48134b
907 "),
908
909 comprehensive_test2("(bool,string,uint8,uint8,uint8,uint8[])", "
910 0000000000000000000000000000000000000000000000000000000000000001
911 00000000000000000000000000000000000000000000000000000000000000c0
912 0000000000000000000000000000000000000000000000000000000000000002
913 0000000000000000000000000000000000000000000000000000000000000003
914 0000000000000000000000000000000000000000000000000000000000000004
915 0000000000000000000000000000000000000000000000000000000000000100
916 0000000000000000000000000000000000000000000000000000000000000009
917 6761766f66796f726b0000000000000000000000000000000000000000000000
918 0000000000000000000000000000000000000000000000000000000000000003
919 0000000000000000000000000000000000000000000000000000000000000005
920 0000000000000000000000000000000000000000000000000000000000000006
921 0000000000000000000000000000000000000000000000000000000000000007
922 "),
923
924 dynamic_array_of_bytes("bytes[]", "
925 0000000000000000000000000000000000000000000000000000000000000020
926 0000000000000000000000000000000000000000000000000000000000000001
927 0000000000000000000000000000000000000000000000000000000000000020
928 0000000000000000000000000000000000000000000000000000000000000026
929 019c80031b20d5e69c8093a571162299032018d913930d93ab320ae5ea44a421
930 8a274f00d6070000000000000000000000000000000000000000000000000000
931 "),
932
933 dynamic_array_of_bytes2("bytes[]", "
934 0000000000000000000000000000000000000000000000000000000000000020
935 0000000000000000000000000000000000000000000000000000000000000002
936 0000000000000000000000000000000000000000000000000000000000000040
937 00000000000000000000000000000000000000000000000000000000000000a0
938 0000000000000000000000000000000000000000000000000000000000000026
939 4444444444444444444444444444444444444444444444444444444444444444
940 4444444444440000000000000000000000000000000000000000000000000000
941 0000000000000000000000000000000000000000000000000000000000000026
942 6666666666666666666666666666666666666666666666666666666666666666
943 6666666666660000000000000000000000000000000000000000000000000000
944 "),
945
946 static_tuple_of_addresses("(address,address)", "
947 0000000000000000000000001111111111111111111111111111111111111111
948 0000000000000000000000002222222222222222222222222222222222222222
949 "),
950
951 dynamic_tuple("((string,string),)", "
952 0000000000000000000000000000000000000000000000000000000000000020
953 0000000000000000000000000000000000000000000000000000000000000040
954 0000000000000000000000000000000000000000000000000000000000000080
955 0000000000000000000000000000000000000000000000000000000000000009
956 6761766f66796f726b0000000000000000000000000000000000000000000000
957 0000000000000000000000000000000000000000000000000000000000000009
958 6761766f66796f726b0000000000000000000000000000000000000000000000
959 "),
960
961 dynamic_tuple_of_bytes("((bytes,bytes),)", "
962 0000000000000000000000000000000000000000000000000000000000000020
963 0000000000000000000000000000000000000000000000000000000000000040
964 00000000000000000000000000000000000000000000000000000000000000a0
965 0000000000000000000000000000000000000000000000000000000000000026
966 4444444444444444444444444444444444444444444444444444444444444444
967 4444444444440000000000000000000000000000000000000000000000000000
968 0000000000000000000000000000000000000000000000000000000000000026
969 6666666666666666666666666666666666666666666666666666666666666666
970 6666666666660000000000000000000000000000000000000000000000000000
971 "),
972
973 complex_tuple("((uint256,string,address,address),)", "
974 0000000000000000000000000000000000000000000000000000000000000020
975 1111111111111111111111111111111111111111111111111111111111111111
976 0000000000000000000000000000000000000000000000000000000000000080
977 0000000000000000000000001111111111111111111111111111111111111111
978 0000000000000000000000002222222222222222222222222222222222222222
979 0000000000000000000000000000000000000000000000000000000000000009
980 6761766f66796f726b0000000000000000000000000000000000000000000000
981 "),
982
983 nested_tuple("((string,bool,string,(string,string,(string,string))),)", "
984 0000000000000000000000000000000000000000000000000000000000000020
985 0000000000000000000000000000000000000000000000000000000000000080
986 0000000000000000000000000000000000000000000000000000000000000001
987 00000000000000000000000000000000000000000000000000000000000000c0
988 0000000000000000000000000000000000000000000000000000000000000100
989 0000000000000000000000000000000000000000000000000000000000000004
990 7465737400000000000000000000000000000000000000000000000000000000
991 0000000000000000000000000000000000000000000000000000000000000006
992 6379626f72670000000000000000000000000000000000000000000000000000
993 0000000000000000000000000000000000000000000000000000000000000060
994 00000000000000000000000000000000000000000000000000000000000000a0
995 00000000000000000000000000000000000000000000000000000000000000e0
996 0000000000000000000000000000000000000000000000000000000000000005
997 6e69676874000000000000000000000000000000000000000000000000000000
998 0000000000000000000000000000000000000000000000000000000000000003
999 6461790000000000000000000000000000000000000000000000000000000000
1000 0000000000000000000000000000000000000000000000000000000000000040
1001 0000000000000000000000000000000000000000000000000000000000000080
1002 0000000000000000000000000000000000000000000000000000000000000004
1003 7765656500000000000000000000000000000000000000000000000000000000
1004 0000000000000000000000000000000000000000000000000000000000000008
1005 66756e7465737473000000000000000000000000000000000000000000000000
1006 "),
1007
1008 params_containing_dynamic_tuple("(address,(bool,string,string),address,address,bool)", "
1009 0000000000000000000000002222222222222222222222222222222222222222
1010 00000000000000000000000000000000000000000000000000000000000000a0
1011 0000000000000000000000003333333333333333333333333333333333333333
1012 0000000000000000000000004444444444444444444444444444444444444444
1013 0000000000000000000000000000000000000000000000000000000000000000
1014 0000000000000000000000000000000000000000000000000000000000000001
1015 0000000000000000000000000000000000000000000000000000000000000060
1016 00000000000000000000000000000000000000000000000000000000000000a0
1017 0000000000000000000000000000000000000000000000000000000000000009
1018 7370616365736869700000000000000000000000000000000000000000000000
1019 0000000000000000000000000000000000000000000000000000000000000006
1020 6379626f72670000000000000000000000000000000000000000000000000000
1021 "),
1022
1023 params_containing_static_tuple("(address,(address,bool,bool),address,address)", "
1024 0000000000000000000000001111111111111111111111111111111111111111
1025 0000000000000000000000002222222222222222222222222222222222222222
1026 0000000000000000000000000000000000000000000000000000000000000001
1027 0000000000000000000000000000000000000000000000000000000000000000
1028 0000000000000000000000003333333333333333333333333333333333333333
1029 0000000000000000000000004444444444444444444444444444444444444444
1030 "),
1031
1032 dynamic_tuple_with_nested_static_tuples("((((bool,uint16),),uint16[]),)", "
1033 0000000000000000000000000000000000000000000000000000000000000020
1034 0000000000000000000000000000000000000000000000000000000000000000
1035 0000000000000000000000000000000000000000000000000000000000000777
1036 0000000000000000000000000000000000000000000000000000000000000060
1037 0000000000000000000000000000000000000000000000000000000000000002
1038 0000000000000000000000000000000000000000000000000000000000000042
1039 0000000000000000000000000000000000000000000000000000000000001337
1040 "),
1041
1042 tuple_array("((uint256,)[],uint256)", "
1044 0000000000000000000000000000000000000000000000000000000000000040
1045 000000000000000000000000000000000000000000000000000000000000007b
1046 0000000000000000000000000000000000000000000000000000000000000001
1047 0000000000000000000000000000000000000000000000000000000000000001
1048 "),
1049 nested_tuple_array("(((uint256,)[],uint256),)", "
1050 0000000000000000000000000000000000000000000000000000000000000020
1051 0000000000000000000000000000000000000000000000000000000000000040
1052 000000000000000000000000000000000000000000000000000000000000007b
1053 0000000000000000000000000000000000000000000000000000000000000001
1054 0000000000000000000000000000000000000000000000000000000000000001
1055 "),
1056 }
1057
1058 #[test]
1060 fn zst_dos() {
1061 let my_type: DynSolType = "()[]".parse().unwrap();
1062 let value = my_type.abi_decode(&hex!("000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000FFFFFFFF"));
1063 assert_eq!(value, Ok(DynSolValue::Array(vec![])));
1064 }
1065
1066 #[test]
1067 #[cfg_attr(miri, ignore = "takes too long")]
1068 fn recursive_dos() {
1069 let payload = "0000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000a0000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000020";
1071
1072 let my_type: DynSolType = "uint256[][][][][][][][][][]".parse().unwrap();
1074 let decoded = my_type.abi_decode(&hex::decode(payload).unwrap());
1075 assert_eq!(decoded, Err(alloy_sol_types::Error::RecursionLimitExceeded(16).into()));
1076
1077 let payload = &"0000000000000000000000000000000000000000000000000000000000000020\
1079 000000000000000000000000000000000000000000000000000000000000000a\
1080 0000000000000000000000000000000000000000000000000000000000000020"
1081 .repeat(64);
1082 let my_type: DynSolType = "uint256[][][][][][][][][][]".parse().unwrap();
1083 let decoded = my_type.abi_decode(&hex::decode(payload).unwrap());
1084 assert_eq!(
1085 decoded,
1086 Err(alloy_sol_types::Error::TypeCheckFail {
1087 expected_type: "offset (usize)".into(),
1088 data: "0000000000000000000000000000000000000000000a00000000000000000000"
1089 .to_string()
1090 }
1091 .into())
1092 );
1093
1094 let my_type: DynSolType = "bytes[][][][][][][][][][]".parse().unwrap();
1095 let decoded = my_type.abi_decode(&hex::decode(payload).unwrap());
1096 assert_eq!(
1097 decoded,
1098 Err(alloy_sol_types::Error::TypeCheckFail {
1099 expected_type: "offset (usize)".into(),
1100 data: "0000000000000000000000000000000000000000000a00000000000000000000"
1101 .to_string()
1102 }
1103 .into())
1104 );
1105 }
1106
1107 #[test]
1109 fn large_dyn_array_dos() {
1110 let payload = "000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000FFFFFFFF";
1111
1112 let my_type: DynSolType = "uint32[1][]".parse().unwrap();
1114 let decoded = my_type.abi_decode(&hex::decode(payload).unwrap());
1115 assert_eq!(decoded, Err(alloy_sol_types::Error::Overrun.into()))
1116 }
1117
1118 #[test]
1119 fn fixed_array_dos() {
1120 let t = "uint32[9999999999]".parse::<DynSolType>().unwrap();
1121 let decoded = t.abi_decode(&[]);
1122 assert_eq!(decoded, Err(alloy_sol_types::Error::Overrun.into()))
1123 }
1124
1125 macro_rules! packed_tests {
1126 ($($name:ident($ty:literal, $v:literal, $encoded:literal)),* $(,)?) => {
1127 mod packed {
1128 use super::*;
1129
1130 $(
1131 #[test]
1132 fn $name() {
1133 packed_test($ty, $v, &hex!($encoded));
1134 }
1135 )*
1136 }
1137 };
1138 }
1139
1140 fn packed_test(t_s: &str, v_s: &str, expected: &[u8]) {
1141 let ty: DynSolType = t_s.parse().expect("parsing failed");
1142 assert_eq!(ty.sol_type_name(), t_s, "type names are not the same");
1143
1144 let value = match ty.coerce_str(v_s) {
1145 Ok(v) => v,
1146 Err(e) => {
1147 panic!("failed to coerce to a value: {e}");
1148 }
1149 };
1150 if let Some(value_name) = value.sol_type_name() {
1151 assert_eq!(value_name, t_s, "value names are not the same");
1152 }
1153
1154 let packed = value.abi_encode_packed();
1155 assert!(
1156 packed == expected,
1157 "
1158 type: {ty}
1159 value: {value:?}
1160 packed: {packed}
1161expected: {expected}",
1162 packed = hex::encode(packed),
1163 expected = hex::encode(expected),
1164 );
1165 }
1166
1167 packed_tests! {
1168 address("address", "1111111111111111111111111111111111111111", "1111111111111111111111111111111111111111"),
1169
1170 bool_false("bool", "false", "00"),
1171 bool_true("bool", "true", "01"),
1172
1173 int8_1("int8", "0", "00"),
1174 int8_2("int8", "1", "01"),
1175 int8_3("int8", "16", "10"),
1176 int8_4("int8", "127", "7f"),
1177 neg_int8_1("int8", "-1", "ff"),
1178 neg_int8_2("int8", "-16", "f0"),
1179 neg_int8_3("int8", "-127", "81"),
1180 neg_int8_4("int8", "-128", "80"),
1181
1182 int16_1("int16", "0", "0000"),
1183 int16_2("int16", "1", "0001"),
1184 int16_3("int16", "16", "0010"),
1185 int16_4("int16", "127", "007f"),
1186 int16_5("int16", "128", "0080"),
1187 int16_6("int16", "8192", "2000"),
1188 int16_7("int16", "32767", "7fff"),
1189 neg_int16_1("int16", "-1", "ffff"),
1190 neg_int16_2("int16", "-16", "fff0"),
1191 neg_int16_3("int16", "-127", "ff81"),
1192 neg_int16_4("int16", "-128", "ff80"),
1193 neg_int16_5("int16", "-129", "ff7f"),
1194 neg_int16_6("int16", "-32767", "8001"),
1195 neg_int16_7("int16", "-32768", "8000"),
1196
1197 int32_1("int32", "0", "00000000"),
1198 int32_2("int32", "-1", "ffffffff"),
1199 int64_1("int64", "0", "0000000000000000"),
1200 int64_2("int64", "-1", "ffffffffffffffff"),
1201 int128_1("int128", "0", "00000000000000000000000000000000"),
1202 int128_2("int128", "-1", "ffffffffffffffffffffffffffffffff"),
1203 int256_1("int256", "0", "0000000000000000000000000000000000000000000000000000000000000000"),
1204 int256_2("int256", "-1", "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"),
1205
1206 uint8_1("uint8", "0", "00"),
1207 uint8_2("uint8", "1", "01"),
1208 uint8_3("uint8", "16", "10"),
1209 uint16("uint16", "0", "0000"),
1210 uint32("uint32", "0", "00000000"),
1211 uint64("uint64", "0", "0000000000000000"),
1212 uint128("uint128", "0", "00000000000000000000000000000000"),
1213 uint256_1("uint256", "0", "0000000000000000000000000000000000000000000000000000000000000000"),
1214 uint256_2("uint256", "42", "000000000000000000000000000000000000000000000000000000000000002a"),
1215 uint256_3("uint256", "115792089237316195423570985008687907853269984665640564039457584007913129639935", "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"),
1216
1217 string_1("string", "a", "61"),
1218 string_2("string", "ab", "6162"),
1219 string_3("string", "abc", "616263"),
1220
1221 bytes_1("bytes", "00", "00"),
1222 bytes_2("bytes", "0001", "0001"),
1223 bytes_3("bytes", "000102", "000102"),
1224
1225 fbytes_1("bytes1", "00", "00"),
1226 fbytes_2("bytes2", "1234", "1234"),
1227 fbytes_3("(address,bytes20)", "(\
1228 1111111111111111111111111111111111111111,\
1229 2222222222222222222222222222222222222222\
1230 )", "
1231 1111111111111111111111111111111111111111
1232 2222222222222222222222222222222222222222
1233 "),
1234 fbytes_4("bytes20[]", "[\
1235 1111111111111111111111111111111111111111,\
1236 2222222222222222222222222222222222222222\
1237 ]", "
1238 0000000000000000000000001111111111111111111111111111111111111111
1239 0000000000000000000000002222222222222222222222222222222222222222
1240 "),
1241 fbytes_5("bytes20[2]", "[\
1242 1111111111111111111111111111111111111111,\
1243 2222222222222222222222222222222222222222\
1244 ]", "
1245 0000000000000000000000001111111111111111111111111111111111111111
1246 0000000000000000000000002222222222222222222222222222222222222222
1247 "),
1248
1249 dynamic_array_of_addresses("address[]", "[\
1250 1111111111111111111111111111111111111111,\
1251 2222222222222222222222222222222222222222\
1252 ]", "
1253 0000000000000000000000001111111111111111111111111111111111111111
1254 0000000000000000000000002222222222222222222222222222222222222222
1255 "),
1256
1257 fixed_array_of_addresses("address[2]", "[\
1258 1111111111111111111111111111111111111111,\
1259 2222222222222222222222222222222222222222\
1260 ]", "
1261 0000000000000000000000001111111111111111111111111111111111111111
1262 0000000000000000000000002222222222222222222222222222222222222222
1263 "),
1264
1265 two_addresses("(address,address)", "(\
1266 1111111111111111111111111111111111111111,\
1267 2222222222222222222222222222222222222222\
1268 )", "
1269 1111111111111111111111111111111111111111
1270 2222222222222222222222222222222222222222
1271 "),
1272
1273 fixed_array_of_dynamic_arrays_of_addresses("address[][2]", "[\
1274 [1111111111111111111111111111111111111111, 2222222222222222222222222222222222222222],\
1275 [3333333333333333333333333333333333333333, 4444444444444444444444444444444444444444]\
1276 ]", "
1277 0000000000000000000000001111111111111111111111111111111111111111
1278 0000000000000000000000002222222222222222222222222222222222222222
1279 0000000000000000000000003333333333333333333333333333333333333333
1280 0000000000000000000000004444444444444444444444444444444444444444
1281 "),
1282
1283 dynamic_array_of_fixed_arrays_of_addresses("address[2][]", "[\
1284 [1111111111111111111111111111111111111111, 2222222222222222222222222222222222222222],\
1285 [3333333333333333333333333333333333333333, 4444444444444444444444444444444444444444]\
1286 ]", "
1287 0000000000000000000000001111111111111111111111111111111111111111
1288 0000000000000000000000002222222222222222222222222222222222222222
1289 0000000000000000000000003333333333333333333333333333333333333333
1290 0000000000000000000000004444444444444444444444444444444444444444
1291 "),
1292
1293 dynamic_array_of_dynamic_arrays("address[][]", "[\
1294 [1111111111111111111111111111111111111111],\
1295 [2222222222222222222222222222222222222222]\
1296 ]", "
1297 0000000000000000000000001111111111111111111111111111111111111111
1298 0000000000000000000000002222222222222222222222222222222222222222
1299 "),
1300
1301 dynamic_array_of_dynamic_arrays2("address[][]", "[\
1302 [1111111111111111111111111111111111111111, 2222222222222222222222222222222222222222],\
1303 [3333333333333333333333333333333333333333, 4444444444444444444444444444444444444444]\
1304 ]", "
1305 0000000000000000000000001111111111111111111111111111111111111111
1306 0000000000000000000000002222222222222222222222222222222222222222
1307 0000000000000000000000003333333333333333333333333333333333333333
1308 0000000000000000000000004444444444444444444444444444444444444444
1309 "),
1310
1311 dynamic_array_of_dynamic_arrays3("uint32[][]", "[\
1312 [1, 2],\
1313 [3, 4]\
1314 ]", "
1315 0000000000000000000000000000000000000000000000000000000000000001
1316 0000000000000000000000000000000000000000000000000000000000000002
1317 0000000000000000000000000000000000000000000000000000000000000003
1318 0000000000000000000000000000000000000000000000000000000000000004
1319 "),
1320 }
1321}