Skip to main content

alloy_sol_types/abi/
decoder.rs

1// Copyright 2015-2020 Parity Technologies
2// Copyright 2023-2023 Alloy Contributors
3//
4// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
5// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
6// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
7// option. This file may not be copied, modified, or distributed
8// except according to those terms.
9//
10
11use crate::{
12    Error, Result, Word,
13    abi::{Token, token::TokenSeq},
14    utils,
15};
16use alloc::vec::Vec;
17use alloy_primitives::hex;
18use core::{cell::Cell, fmt, mem, slice::SliceIndex};
19
20/// The decoder recursion limit.
21///
22/// This is the default value used by [`AbiDecoderConfig`].
23#[deprecated(note = "use `AbiDecoderConfig` to configure the recursion limit")]
24pub const RECURSION_LIMIT: usize = 16;
25
26const DEFAULT_MEMORY_LIMIT: usize = 1 << 30;
27
28/// Configuration for ABI decoding.
29#[allow(missing_copy_implementations, missing_debug_implementations)]
30pub struct AbiDecoderConfig {
31    recursion_limit: usize,
32    memory_limit: usize,
33    validate: bool,
34    strict: bool,
35    validate_allow_trailing_bytes: bool,
36}
37
38impl Default for AbiDecoderConfig {
39    #[inline]
40    fn default() -> Self {
41        Self::new()
42    }
43}
44
45impl Clone for AbiDecoderConfig {
46    #[inline]
47    fn clone(&self) -> Self {
48        *self
49    }
50}
51
52impl Copy for AbiDecoderConfig {}
53
54impl fmt::Debug for AbiDecoderConfig {
55    #[inline]
56    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
57        f.debug_struct("AbiDecoderConfig")
58            .field("recursion_limit", &self.recursion_limit)
59            .field("memory_limit", &self.memory_limit)
60            .field("validate", &self.validate)
61            .field("strict", &self.strict)
62            .field("validate_allow_trailing_bytes", &self.validate_allow_trailing_bytes)
63            .finish()
64    }
65}
66
67impl AbiDecoderConfig {
68    /// Creates a decoder configuration with the default limits.
69    #[inline]
70    pub const fn new() -> Self {
71        Self {
72            recursion_limit: 16,
73            memory_limit: DEFAULT_MEMORY_LIMIT,
74            validate: false,
75            strict: false,
76            validate_allow_trailing_bytes: false,
77        }
78    }
79
80    /// Returns the maximum recursion depth.
81    #[inline]
82    pub const fn get_recursion_limit(&self) -> usize {
83        self.recursion_limit
84    }
85
86    /// Returns the maximum amount of memory that decoding may allocate.
87    #[inline]
88    pub const fn get_memory_limit(&self) -> usize {
89        self.memory_limit
90    }
91
92    /// Returns whether decoded tokens are validated before detokenization.
93    #[inline]
94    pub const fn get_validate(&self) -> bool {
95        self.validate || self.get_strict()
96    }
97
98    /// Returns whether strict ABI encoding is required.
99    ///
100    /// Trailing bytes are permitted when
101    /// [`get_validate_allow_trailing_bytes`](Self::get_validate_allow_trailing_bytes)
102    /// is enabled.
103    #[inline]
104    pub const fn get_strict(&self) -> bool {
105        self.strict
106    }
107
108    /// Returns whether strict validation permits trailing bytes.
109    #[inline]
110    pub const fn get_validate_allow_trailing_bytes(&self) -> bool {
111        self.validate_allow_trailing_bytes
112    }
113
114    /// Sets the maximum recursion depth.
115    #[inline]
116    pub const fn recursion_limit(mut self, limit: usize) -> Self {
117        self.recursion_limit = limit;
118        self
119    }
120
121    /// Sets the maximum amount of memory that decoding may allocate.
122    #[inline]
123    pub const fn memory_limit(mut self, limit: usize) -> Self {
124        self.memory_limit = limit;
125        self
126    }
127
128    /// Enables or disables decoded token validation before detokenization.
129    ///
130    /// When enabled, high-level ABI decode helpers call the target Solidity
131    /// type's token validator before converting the token into the returned
132    /// Rust value. This rejects dirty bool bytes, invalid strings, and other
133    /// token values that can be decoded from ABI words but do not satisfy the
134    /// target type's validity rules.
135    #[inline]
136    pub const fn validate(mut self, validate: bool) -> Self {
137        self.validate = validate;
138        self
139    }
140
141    /// Requires strictly ABI-encoded input.
142    ///
143    /// Strict mode implies `validate`.
144    /// It also rejects gaps or overlaps between dynamic data areas while decoding.
145    /// Trailing bytes are rejected unless
146    /// [`validate_allow_trailing_bytes`](Self::validate_allow_trailing_bytes) is enabled.
147    #[inline]
148    pub const fn strict(mut self, strict: bool) -> Self {
149        self.strict = strict;
150        self
151    }
152
153    /// Allows trailing bytes when strict ABI decoding is enabled.
154    ///
155    /// This does not enable [`strict`](Self::strict) or [`validate`](Self::validate).
156    /// In strict mode, it skips the final check that the encoding consumes the entire
157    /// input. All other strict checks, including canonical offsets, complete zero padding,
158    /// and token validation, remain enabled. This matches Solidity's acceptance of trailing
159    /// bytes only; it does not relax the other checks that Solidity omits. Without strict
160    /// mode, trailing bytes are already permitted.
161    ///
162    /// This option permits trailing bytes even when `strict(true)` is also set,
163    /// regardless of setter order. Disabling it leaves the other configuration flags
164    /// unchanged.
165    ///
166    /// ```
167    /// use alloy_sol_types::{SolType, abi::AbiDecoderConfig, sol_data::Uint};
168    ///
169    /// let mut data = Uint::<8>::abi_encode(&42);
170    /// data.extend_from_slice(&[0xaa, 0xbb]);
171    /// let config = AbiDecoderConfig::new().strict(true).validate_allow_trailing_bytes(true);
172    /// assert_eq!(Uint::<8>::abi_decode_with_config(&data, config)?, 42);
173    /// # Ok::<(), alloy_sol_types::Error>(())
174    /// ```
175    #[inline]
176    pub const fn validate_allow_trailing_bytes(mut self, allow: bool) -> Self {
177        self.validate_allow_trailing_bytes = allow;
178        self
179    }
180
181    /// Sets the maximum recursion depth in place.
182    #[inline]
183    pub const fn set_recursion_limit(&mut self, limit: usize) {
184        self.recursion_limit = limit;
185    }
186
187    /// Sets the maximum amount of memory that decoding may allocate in place.
188    #[inline]
189    pub const fn set_memory_limit(&mut self, limit: usize) {
190        self.memory_limit = limit;
191    }
192
193    /// Enables or disables decoded token validation before detokenization.
194    #[inline]
195    pub const fn set_validate(&mut self, validate: bool) {
196        self.validate = validate;
197    }
198
199    /// Requires or allows non-strict ABI encoding in place.
200    #[inline]
201    pub const fn set_strict(&mut self, strict: bool) {
202        self.strict = strict;
203    }
204
205    /// Sets [`validate_allow_trailing_bytes`](Self::validate_allow_trailing_bytes) in place.
206    #[inline]
207    pub const fn set_validate_allow_trailing_bytes(&mut self, allow: bool) {
208        self.validate_allow_trailing_bytes = allow;
209    }
210}
211
212enum DecoderState<'state> {
213    Root {
214        memory_used: Cell<usize>,
215        strict_next_offset: Cell<usize>,
216    },
217    Child {
218        memory_used: &'state Cell<usize>,
219        strict_next_offset: Cell<usize>,
220        strict_parent: Option<StrictParent<'state>>,
221    },
222}
223
224impl<'state> DecoderState<'state> {
225    #[inline]
226    const fn memory_used(&self) -> &Cell<usize> {
227        match self {
228            Self::Root { memory_used, .. } => memory_used,
229            Self::Child { memory_used, .. } => memory_used,
230        }
231    }
232
233    #[inline]
234    const fn strict_next_offset(&self) -> &Cell<usize> {
235        match self {
236            Self::Root { strict_next_offset, .. } | Self::Child { strict_next_offset, .. } => {
237                strict_next_offset
238            }
239        }
240    }
241
242    #[inline]
243    const fn strict_parent(&self) -> Option<&StrictParent<'state>> {
244        match self {
245            Self::Root { .. } => None,
246            Self::Child { strict_parent, .. } => strict_parent.as_ref(),
247        }
248    }
249}
250
251struct StrictParent<'state> {
252    next_offset: &'state Cell<usize>,
253    start: usize,
254}
255
256/// The [`Decoder`] wraps a byte slice with necessary info to progressively
257/// deserialize the bytes into a sequence of tokens.
258///
259/// # Usage Note
260///
261/// While the Decoder contains the necessary info, the actual deserialization
262/// is done in the [`crate::SolType`] trait.
263pub struct Decoder<'de, 'state> {
264    // The underlying buffer.
265    buf: &'de [u8],
266    // The current offset in the buffer.
267    offset: usize,
268    /// The current recursion depth.
269    depth: usize,
270    /// The decoder configuration.
271    config: AbiDecoderConfig,
272    /// Shared decoder state.
273    state: DecoderState<'state>,
274}
275
276impl fmt::Debug for Decoder<'_, '_> {
277    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
278        let mut body = self.buf.chunks(32).map(hex::encode_prefixed).collect::<Vec<_>>();
279        if let Some(word) = body.get_mut(self.offset / 32) {
280            word.push_str(" <-- Next Word");
281        }
282
283        f.debug_struct("Decoder")
284            .field("buf", &body)
285            .field("offset", &self.offset)
286            .field("depth", &self.depth)
287            .field("config", &self.config)
288            .finish()
289    }
290}
291
292impl fmt::Display for Decoder<'_, '_> {
293    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
294        writeln!(f, "Abi Decode Buffer")?;
295
296        for (i, chunk) in self.buf.chunks(32).enumerate() {
297            let idx = i * 32;
298            writeln!(
299                f,
300                "0x{idx:04x}: {}{}",
301                hex::encode_prefixed(chunk),
302                if idx == self.offset { " <-- Next Word" } else { "" }
303            )?;
304        }
305        Ok(())
306    }
307}
308
309impl<'de> Decoder<'de, 'static> {
310    /// Instantiates a new decoder from a byte slice.
311    #[inline]
312    pub const fn new(buf: &'de [u8]) -> Self {
313        Self::with_config(buf, AbiDecoderConfig::new())
314    }
315
316    #[inline]
317    const fn with_config(buf: &'de [u8], config: AbiDecoderConfig) -> Self {
318        Self {
319            buf,
320            offset: 0,
321            depth: 0,
322            config,
323            state: DecoderState::Root {
324                memory_used: Cell::new(0),
325                strict_next_offset: Cell::new(0),
326            },
327        }
328    }
329}
330
331impl<'de, 'state> Decoder<'de, 'state> {
332    #[inline]
333    const fn new_child<'child>(parent: &'child Self, buf: &'de [u8]) -> Decoder<'de, 'child> {
334        Decoder {
335            buf,
336            offset: 0,
337            depth: parent.depth + 1,
338            config: parent.config,
339            state: DecoderState::Child {
340                memory_used: parent.memory_used(),
341                strict_next_offset: Cell::new(0),
342                strict_parent: if parent.config.get_strict() {
343                    Some(StrictParent {
344                        next_offset: parent.state.strict_next_offset(),
345                        start: parent.buf.len() - buf.len(),
346                    })
347                } else {
348                    None
349                },
350            },
351        }
352    }
353
354    #[inline]
355    const fn memory_used(&self) -> &Cell<usize> {
356        self.state.memory_used()
357    }
358
359    /// Sets the size of the current zone's head in words for strict decoding.
360    #[doc(hidden)]
361    #[inline]
362    pub fn set_strict_head_words(&self, words: usize) -> Result<()> {
363        if self.config.get_strict() {
364            let bytes = words.checked_mul(Word::len_bytes()).ok_or(Error::Overrun)?;
365            let offset = self.offset.checked_add(bytes).ok_or(Error::Overrun)?;
366            let next = self.state.strict_next_offset();
367            next.set(next.get().max(offset));
368        }
369        Ok(())
370    }
371
372    #[inline]
373    pub(crate) const fn is_strict(&self) -> bool {
374        self.config.get_strict()
375    }
376
377    /// Returns the current offset in the buffer.
378    #[inline]
379    pub const fn offset(&self) -> usize {
380        self.offset
381    }
382
383    /// Returns the number of bytes in the remaining buffer.
384    #[inline]
385    pub const fn remaining(&self) -> Option<usize> {
386        self.buf.len().checked_sub(self.offset)
387    }
388
389    /// Returns the number of words in the remaining buffer.
390    #[inline]
391    pub const fn remaining_words(&self) -> usize {
392        if let Some(remaining) = self.remaining() { remaining / Word::len_bytes() } else { 0 }
393    }
394
395    /// Returns a reference to the remaining bytes in the buffer.
396    #[inline]
397    pub fn remaining_buf(&self) -> Option<&'de [u8]> {
398        self.buf.get(self.offset..)
399    }
400
401    /// Returns whether the remaining buffer is empty.
402    #[inline]
403    pub const fn is_empty(&self) -> bool {
404        match self.remaining() {
405            Some(0) | None => true,
406            Some(_) => false,
407        }
408    }
409
410    /// Create a child decoder, starting at `offset` bytes from the current
411    /// decoder's offset.
412    ///
413    /// See [`child`](Self::child).
414    #[inline]
415    pub fn raw_child<'child>(&'child self) -> Result<Decoder<'de, 'child>> {
416        self.child(self.offset)
417    }
418
419    /// Create a child decoder, starting at `offset` bytes from the current
420    /// decoder's offset.
421    /// The child decoder shares the buffer.
422    #[inline]
423    pub fn child<'child>(&'child self, offset: usize) -> Result<Decoder<'de, 'child>, Error> {
424        let recursion_limit = self.config.get_recursion_limit();
425        if self.depth >= recursion_limit {
426            return Err(Error::RecursionLimitExceeded(recursion_limit));
427        }
428        match self.buf.get(offset..) {
429            Some(buf) => Ok(Self::new_child(self, buf)),
430            None => Err(Error::Overrun),
431        }
432    }
433
434    /// Registers an allocation against the configured memory limit.
435    #[doc(hidden)]
436    #[inline]
437    pub fn reserve(&mut self, bytes: usize) -> Result<()> {
438        let memory_limit = self.config.get_memory_limit();
439        let used = self
440            .memory_used()
441            .get()
442            .checked_add(bytes)
443            .ok_or(Error::MemoryLimitExceeded(memory_limit))?;
444        if used > memory_limit {
445            return Err(Error::MemoryLimitExceeded(memory_limit));
446        }
447        self.memory_used().set(used);
448        Ok(())
449    }
450
451    #[doc(hidden)]
452    #[inline]
453    pub fn reserve_elements<T>(&mut self, len: usize) -> Result<()> {
454        let bytes = len
455            .checked_mul(mem::size_of::<T>())
456            .ok_or(Error::MemoryLimitExceeded(self.config.get_memory_limit()))?;
457        self.reserve(bytes)
458    }
459
460    /// Advance the offset by `len` bytes.
461    #[inline]
462    const fn increase_offset(&mut self, len: usize) {
463        self.offset += len;
464    }
465
466    /// Peek into the buffer.
467    #[inline]
468    pub fn peek<I: SliceIndex<[u8]>>(&self, index: I) -> Result<&'de I::Output, Error> {
469        self.buf.get(index).ok_or(Error::Overrun)
470    }
471
472    /// Peek a slice of size `len` from the buffer at a specific offset, without
473    /// advancing the offset.
474    #[inline]
475    pub fn peek_len_at(&self, offset: usize, len: usize) -> Result<&'de [u8], Error> {
476        let end = offset.checked_add(len).ok_or(Error::Overrun)?;
477        self.peek(offset..end)
478    }
479
480    /// Peek a slice of size `len` from the buffer without advancing the offset.
481    #[inline]
482    pub fn peek_len(&self, len: usize) -> Result<&'de [u8], Error> {
483        self.peek_len_at(self.offset, len)
484    }
485
486    /// Peek a word from the buffer at a specific offset, without advancing the
487    /// offset.
488    #[inline]
489    pub fn peek_word_at(&self, offset: usize) -> Result<&'de Word, Error> {
490        self.peek_len_at(offset, Word::len_bytes()).map(|w| <&Word>::try_from(w).unwrap())
491    }
492
493    /// Peek the next word from the buffer without advancing the offset.
494    #[inline]
495    pub fn peek_word(&self) -> Result<&'de Word, Error> {
496        self.peek_word_at(self.offset)
497    }
498
499    /// Peek a `usize` from the buffer at a specific offset, without advancing
500    /// the offset.
501    #[inline]
502    pub fn peek_offset_at(&self, offset: usize) -> Result<usize> {
503        self.peek_word_at(offset).and_then(utils::as_offset)
504    }
505
506    /// Peek a `usize` from the buffer, without advancing the offset.
507    #[inline]
508    pub fn peek_offset(&self) -> Result<usize> {
509        self.peek_word().and_then(utils::as_offset)
510    }
511
512    /// Take a word from the buffer, advancing the offset.
513    #[inline]
514    pub fn take_word(&mut self) -> Result<&'de Word, Error> {
515        let contents = self.peek_word()?;
516        self.increase_offset(Word::len_bytes());
517        Ok(contents)
518    }
519
520    /// Return a child decoder by consuming a word, interpreting it as a
521    /// pointer, and following it.
522    #[inline]
523    pub fn take_indirection<'child>(&'child mut self) -> Result<Decoder<'de, 'child>, Error> {
524        let offset = self.take_offset()?;
525        if self.is_strict() && offset != self.state.strict_next_offset().get() {
526            return Err(Error::ReserMismatch);
527        }
528        self.child(offset)
529    }
530
531    /// Takes a `usize` offset from the buffer by consuming a word.
532    #[inline]
533    pub fn take_offset(&mut self) -> Result<usize> {
534        self.take_word().and_then(utils::as_offset)
535    }
536
537    /// Takes a slice of bytes of the given length.
538    #[inline]
539    pub fn take_slice(&mut self, len: usize) -> Result<&'de [u8]> {
540        self.peek_len(len).inspect(|_| self.increase_offset(len))
541    }
542
543    /// Takes a padded slice and validates its padding in strict mode.
544    #[doc(hidden)]
545    #[inline]
546    pub fn take_padded_slice(&mut self, len: usize) -> Result<&'de [u8]> {
547        let bytes = self.take_slice(len)?;
548        if self.is_strict() {
549            let padding = (Word::len_bytes() - len % Word::len_bytes()) % Word::len_bytes();
550            if self.take_slice(padding)?.iter().any(|&byte| byte != 0) {
551                return Err(Error::ReserMismatch);
552            }
553        }
554        Ok(bytes)
555    }
556
557    /// Takes the offset from the child decoder and sets it as the current
558    /// offset.
559    #[inline]
560    pub const fn take_offset_from(&mut self, child: &Decoder<'de, '_>) {
561        self.set_offset(self.offset_from_child(child));
562    }
563
564    /// Returns the parent-relative offset from a child decoder.
565    #[inline]
566    pub const fn offset_from_child(&self, child: &Decoder<'de, '_>) -> usize {
567        child.offset + (self.buf.len() - child.buf.len())
568    }
569
570    /// Sets the current offset in the buffer.
571    #[inline]
572    pub const fn set_offset(&mut self, offset: usize) {
573        self.offset = offset;
574    }
575
576    /// Decodes a single token from the underlying buffer.
577    #[inline]
578    pub fn decode<T: Token<'de>>(&mut self) -> Result<T> {
579        T::decode_from(self)
580    }
581
582    /// Decodes a sequence of tokens from the underlying buffer.
583    #[inline]
584    pub fn decode_sequence<T: Token<'de> + TokenSeq<'de>>(&mut self) -> Result<T> {
585        T::decode_sequence(self)
586    }
587}
588
589impl Drop for Decoder<'_, '_> {
590    fn drop(&mut self) {
591        if let Some(parent) = self.state.strict_parent() {
592            let offset =
593                parent.start.saturating_add(self.offset.max(self.state.strict_next_offset().get()));
594            parent.next_offset.set(parent.next_offset.get().max(offset));
595        }
596    }
597}
598
599/// ABI-decodes a token by wrapping it in a single-element tuple.
600///
601/// You are probably looking for
602/// [`SolValue::abi_decode`](crate::SolValue::abi_decode) if you are not
603/// intending to use raw tokens.
604///
605/// See the [`abi`](super) module for more information.
606#[inline(always)]
607pub fn decode<'de, T: Token<'de>>(data: &'de [u8]) -> Result<T> {
608    decode_with_config(data, AbiDecoderConfig::default())
609}
610
611/// ABI-decodes a token with the given configuration.
612#[inline(always)]
613pub fn decode_with_config<'de, T: Token<'de>>(
614    data: &'de [u8],
615    config: AbiDecoderConfig,
616) -> Result<T> {
617    decode_sequence_with_config::<(T,)>(data, config).map(|(t,)| t)
618}
619
620/// ABI-decodes top-level function args.
621///
622/// Decodes as function parameters if [`T` is a tuple](TokenSeq::IS_TUPLE).
623/// Otherwise, decodes it as a single-element tuple.
624///
625/// You are probably looking for
626/// [`SolValue::abi_decode_params`](crate::SolValue::abi_decode_params) if
627/// you are not intending to use raw tokens.
628///
629/// See the [`abi`](super) module for more information.
630#[inline(always)]
631pub fn decode_params<'de, T: TokenSeq<'de>>(data: &'de [u8]) -> Result<T> {
632    decode_params_with_config(data, AbiDecoderConfig::default())
633}
634
635/// ABI-decodes top-level function args with the given configuration.
636#[inline(always)]
637pub fn decode_params_with_config<'de, T: TokenSeq<'de>>(
638    data: &'de [u8],
639    config: AbiDecoderConfig,
640) -> Result<T> {
641    if T::IS_TUPLE {
642        decode_sequence_with_config(data, config)
643    } else {
644        decode_with_config(data, config)
645    }
646}
647
648/// Decodes ABI compliant vector of bytes into vector of tokens described by
649/// types param.
650///
651/// You are probably looking for
652/// [`SolValue::abi_decode_sequence`](crate::SolValue::abi_decode_sequence) if
653/// you are not intending to use raw tokens.
654///
655/// See the [`abi`](super) module for more information.
656#[inline]
657pub fn decode_sequence<'de, T: TokenSeq<'de>>(data: &'de [u8]) -> Result<T> {
658    decode_sequence_with_config(data, AbiDecoderConfig::default())
659}
660
661/// Decodes an ABI-compliant sequence into tokens with the given configuration.
662#[inline]
663pub fn decode_sequence_with_config<'de, T: TokenSeq<'de>>(
664    data: &'de [u8],
665    config: AbiDecoderConfig,
666) -> Result<T> {
667    let mut decoder = Decoder::with_config(data, config);
668    let result = decoder.decode_sequence::<T>()?;
669    if config.get_strict()
670        && !config.get_validate_allow_trailing_bytes()
671        && decoder.state.strict_next_offset().get() != data.len()
672    {
673        return Err(Error::ReserMismatch);
674    }
675    Ok(result)
676}
677
678#[cfg(test)]
679mod tests {
680    use super::*;
681    use crate::{SolCall, SolType, SolValue, sol, sol_data, utils::pad_usize};
682    use alloc::string::ToString;
683    use alloy_primitives::{Address, B256, U256, address, bytes, hex};
684
685    #[test]
686    fn dynamic_array_of_dynamic_arrays() {
687        type MyTy = sol_data::Array<sol_data::Array<sol_data::Address>>;
688        let encoded = hex!(
689            "
690    		0000000000000000000000000000000000000000000000000000000000000020
691    		0000000000000000000000000000000000000000000000000000000000000002
692    		0000000000000000000000000000000000000000000000000000000000000040
693    		0000000000000000000000000000000000000000000000000000000000000080
694    		0000000000000000000000000000000000000000000000000000000000000001
695    		0000000000000000000000001111111111111111111111111111111111111111
696    		0000000000000000000000000000000000000000000000000000000000000001
697    		0000000000000000000000002222222222222222222222222222222222222222
698    	"
699        );
700
701        let ty = vec![vec![Address::repeat_byte(0x11)], vec![Address::repeat_byte(0x22)]];
702        assert_eq!(MyTy::abi_encode_params(&ty), encoded);
703
704        let decoded = MyTy::abi_decode_params(&encoded).unwrap();
705        assert_eq!(decoded, ty);
706        assert_eq!(decoded.abi_encode_params(), encoded);
707        assert_eq!(decoded.abi_encoded_size(), encoded.len());
708    }
709
710    #[test]
711    fn decode_static_tuple_of_addresses_and_uints() {
712        type MyTy = (sol_data::Address, sol_data::Address, sol_data::Uint<256>);
713
714        let encoded = hex!(
715            "
716    		0000000000000000000000001111111111111111111111111111111111111111
717    		0000000000000000000000002222222222222222222222222222222222222222
718    		1111111111111111111111111111111111111111111111111111111111111111
719    	"
720        );
721        let address1 = Address::from([0x11u8; 20]);
722        let address2 = Address::from([0x22u8; 20]);
723        let uint = U256::from_be_bytes::<32>([0x11u8; 32]);
724        let expected = (address1, address2, uint);
725        let decoded = MyTy::abi_decode_sequence(&encoded).unwrap();
726        assert_eq!(decoded, expected);
727        assert_eq!(decoded.abi_encode_params(), encoded);
728        assert_eq!(decoded.abi_encoded_size(), encoded.len());
729    }
730
731    #[test]
732    fn decode_dynamic_tuple() {
733        type MyTy = (sol_data::String, sol_data::String);
734        let encoded = hex!(
735            "
736    		0000000000000000000000000000000000000000000000000000000000000020
737    		0000000000000000000000000000000000000000000000000000000000000040
738    		0000000000000000000000000000000000000000000000000000000000000080
739    		0000000000000000000000000000000000000000000000000000000000000009
740    		6761766f66796f726b0000000000000000000000000000000000000000000000
741    		0000000000000000000000000000000000000000000000000000000000000009
742    		6761766f66796f726b0000000000000000000000000000000000000000000000
743    	"
744        );
745        let string1 = "gavofyork".to_string();
746        let string2 = "gavofyork".to_string();
747        let expected = (string1, string2);
748
749        // this test vector contains a top-level indirect
750        let decoded = MyTy::abi_decode(&encoded).unwrap();
751        assert_eq!(decoded, expected);
752        assert_eq!(decoded.abi_encode(), encoded);
753        assert_eq!(decoded.abi_encoded_size(), encoded.len());
754    }
755
756    #[test]
757    fn decode_nested_tuple() {
758        type MyTy = (
759            sol_data::String,
760            sol_data::Bool,
761            sol_data::String,
762            (sol_data::String, sol_data::String, (sol_data::String, sol_data::String)),
763        );
764
765        let encoded = hex!(
766            "
767    		0000000000000000000000000000000000000000000000000000000000000020
768    		0000000000000000000000000000000000000000000000000000000000000080
769    		0000000000000000000000000000000000000000000000000000000000000001
770    		00000000000000000000000000000000000000000000000000000000000000c0
771    		0000000000000000000000000000000000000000000000000000000000000100
772    		0000000000000000000000000000000000000000000000000000000000000004
773    		7465737400000000000000000000000000000000000000000000000000000000
774    		0000000000000000000000000000000000000000000000000000000000000006
775    		6379626f72670000000000000000000000000000000000000000000000000000
776    		0000000000000000000000000000000000000000000000000000000000000060
777    		00000000000000000000000000000000000000000000000000000000000000a0
778    		00000000000000000000000000000000000000000000000000000000000000e0
779    		0000000000000000000000000000000000000000000000000000000000000005
780    		6e69676874000000000000000000000000000000000000000000000000000000
781    		0000000000000000000000000000000000000000000000000000000000000003
782    		6461790000000000000000000000000000000000000000000000000000000000
783    		0000000000000000000000000000000000000000000000000000000000000040
784    		0000000000000000000000000000000000000000000000000000000000000080
785    		0000000000000000000000000000000000000000000000000000000000000004
786    		7765656500000000000000000000000000000000000000000000000000000000
787    		0000000000000000000000000000000000000000000000000000000000000008
788    		66756e7465737473000000000000000000000000000000000000000000000000
789    	"
790        );
791        let string1 = "test".into();
792        let string2 = "cyborg".into();
793        let string3 = "night".into();
794        let string4 = "day".into();
795        let string5 = "weee".into();
796        let string6 = "funtests".into();
797        let bool = true;
798        let deep_tuple = (string5, string6);
799        let inner_tuple = (string3, string4, deep_tuple);
800        let expected = (string1, bool, string2, inner_tuple);
801
802        let decoded = MyTy::abi_decode(&encoded).unwrap();
803        assert_eq!(decoded, expected);
804        assert_eq!(decoded.abi_encode(), encoded);
805        assert_eq!(decoded.abi_encoded_size(), encoded.len());
806    }
807
808    #[test]
809    fn decode_complex_tuple_of_dynamic_and_static_types() {
810        type MyTy = (sol_data::Uint<256>, sol_data::String, sol_data::Address, sol_data::Address);
811
812        let encoded = hex!(
813            "
814    		0000000000000000000000000000000000000000000000000000000000000020
815    		1111111111111111111111111111111111111111111111111111111111111111
816    		0000000000000000000000000000000000000000000000000000000000000080
817    		0000000000000000000000001111111111111111111111111111111111111111
818    		0000000000000000000000002222222222222222222222222222222222222222
819    		0000000000000000000000000000000000000000000000000000000000000009
820    		6761766f66796f726b0000000000000000000000000000000000000000000000
821    	"
822        );
823        let uint = U256::from_be_bytes::<32>([0x11u8; 32]);
824        let string = "gavofyork".to_string();
825        let address1 = Address::from([0x11u8; 20]);
826        let address2 = Address::from([0x22u8; 20]);
827        let expected = (uint, string, address1, address2);
828
829        let decoded = MyTy::abi_decode(&encoded).unwrap();
830        assert_eq!(decoded, expected);
831        assert_eq!(decoded.abi_encode(), encoded);
832        assert_eq!(decoded.abi_encoded_size(), encoded.len());
833    }
834
835    #[test]
836    fn decode_params_containing_dynamic_tuple() {
837        type MyTy = (
838            sol_data::Address,
839            (sol_data::Bool, sol_data::String, sol_data::String),
840            sol_data::Address,
841            sol_data::Address,
842            sol_data::Bool,
843        );
844
845        let encoded = hex!(
846            "
847    		0000000000000000000000002222222222222222222222222222222222222222
848    		00000000000000000000000000000000000000000000000000000000000000a0
849    		0000000000000000000000003333333333333333333333333333333333333333
850    		0000000000000000000000004444444444444444444444444444444444444444
851    		0000000000000000000000000000000000000000000000000000000000000000
852    		0000000000000000000000000000000000000000000000000000000000000001
853    		0000000000000000000000000000000000000000000000000000000000000060
854    		00000000000000000000000000000000000000000000000000000000000000a0
855    		0000000000000000000000000000000000000000000000000000000000000009
856    		7370616365736869700000000000000000000000000000000000000000000000
857    		0000000000000000000000000000000000000000000000000000000000000006
858    		6379626f72670000000000000000000000000000000000000000000000000000
859    	"
860        );
861        let address1 = Address::from([0x22u8; 20]);
862        let bool1 = true;
863        let string1 = "spaceship".to_string();
864        let string2 = "cyborg".to_string();
865        let tuple = (bool1, string1, string2);
866        let address2 = Address::from([0x33u8; 20]);
867        let address3 = Address::from([0x44u8; 20]);
868        let bool2 = false;
869        let expected = (address1, tuple, address2, address3, bool2);
870
871        let decoded = MyTy::abi_decode_params(&encoded).unwrap();
872        assert_eq!(decoded, expected);
873        assert_eq!(decoded.abi_encode_params(), encoded);
874        assert_eq!(decoded.abi_encoded_size(), encoded.len() + 32);
875    }
876
877    #[test]
878    fn decode_params_containing_static_tuple() {
879        type MyTy = (
880            sol_data::Address,
881            (sol_data::Address, sol_data::Bool, sol_data::Bool),
882            sol_data::Address,
883            sol_data::Address,
884        );
885
886        let encoded = hex!(
887            "
888    		0000000000000000000000001111111111111111111111111111111111111111
889    		0000000000000000000000002222222222222222222222222222222222222222
890    		0000000000000000000000000000000000000000000000000000000000000001
891    		0000000000000000000000000000000000000000000000000000000000000000
892    		0000000000000000000000003333333333333333333333333333333333333333
893    		0000000000000000000000004444444444444444444444444444444444444444
894    	"
895        );
896        let address1 = Address::from([0x11u8; 20]);
897        let address2 = Address::from([0x22u8; 20]);
898        let bool1 = true;
899        let bool2 = false;
900        let tuple = (address2, bool1, bool2);
901        let address3 = Address::from([0x33u8; 20]);
902        let address4 = Address::from([0x44u8; 20]);
903
904        let expected = (address1, tuple, address3, address4);
905
906        let decoded = MyTy::abi_decode_params(&encoded).unwrap();
907        assert_eq!(decoded, expected);
908    }
909
910    #[test]
911    fn decode_data_with_size_that_is_not_a_multiple_of_32() {
912        type MyTy = (
913            sol_data::Uint<256>,
914            sol_data::String,
915            sol_data::String,
916            sol_data::Uint<256>,
917            sol_data::Uint<256>,
918        );
919
920        let data = (
921            pad_usize(0).into(),
922            "12203967b532a0c14c980b5aeffb17048bdfaef2c293a9509f08eb3c6b0f5f8f0942e7b9cc76ca51cca26ce546920448e308fda6870b5e2ae12a2409d942de428113P720p30fps16x9".to_string(),
923            "93c717e7c0a6517a".to_string(),
924            pad_usize(1).into(),
925            pad_usize(5538829).into()
926        );
927
928        let encoded = hex!(
929            "
930            0000000000000000000000000000000000000000000000000000000000000000
931            00000000000000000000000000000000000000000000000000000000000000a0
932            0000000000000000000000000000000000000000000000000000000000000152
933            0000000000000000000000000000000000000000000000000000000000000001
934            000000000000000000000000000000000000000000000000000000000054840d
935            0000000000000000000000000000000000000000000000000000000000000092
936            3132323033393637623533326130633134633938306235616566666231373034
937            3862646661656632633239336139353039663038656233633662306635663866
938            3039343265376239636337366361353163636132366365353436393230343438
939            6533303866646136383730623565326165313261323430396439343264653432
940            3831313350373230703330667073313678390000000000000000000000000000
941            0000000000000000000000000000000000103933633731376537633061363531
942            3761
943        "
944        );
945
946        assert_eq!(MyTy::abi_decode_sequence(&encoded).unwrap(), data);
947    }
948
949    #[test]
950    fn decode_after_fixed_bytes_with_less_than_32_bytes() {
951        type MyTy = (
952            sol_data::Address,
953            sol_data::FixedBytes<32>,
954            sol_data::FixedBytes<4>,
955            sol_data::String,
956        );
957
958        let encoded = hex!(
959            "
960    		0000000000000000000000008497afefdc5ac170a664a231f6efb25526ef813f
961    		0101010101010101010101010101010101010101010101010101010101010101
962    		0202020202020202020202020202020202020202020202020202020202020202
963    		0000000000000000000000000000000000000000000000000000000000000080
964    		000000000000000000000000000000000000000000000000000000000000000a
965    		3078303030303030314600000000000000000000000000000000000000000000
966    	    "
967        );
968
969        assert_eq!(
970            MyTy::abi_decode_params(&encoded).unwrap(),
971            (
972                address!("0x8497afefdc5ac170a664a231f6efb25526ef813f"),
973                B256::repeat_byte(0x01),
974                [0x02; 4].into(),
975                "0x0000001F".into(),
976            )
977        );
978    }
979
980    #[test]
981    fn decode_broken_utf8() {
982        let encoded = hex!(
983            "
984    		0000000000000000000000000000000000000000000000000000000000000020
985    		0000000000000000000000000000000000000000000000000000000000000004
986    		e4b88de500000000000000000000000000000000000000000000000000000000
987            "
988        );
989
990        assert_eq!(sol_data::String::abi_decode(&encoded).unwrap(), "不�".to_string());
991    }
992
993    #[test]
994    #[cfg_attr(miri, ignore = "OOM https://github.com/rust-lang/miri/issues/3637")]
995    fn decode_corrupted_dynamic_array() {
996        type MyTy = sol_data::Array<sol_data::Uint<32>>;
997        // line 1 at 0x00 =   0: tail offset of array
998        // line 2 at 0x20 =  32: length of array
999        // line 3 at 0x40 =  64: first word
1000        // line 4 at 0x60 =  96: second word
1001        let encoded = hex!(
1002            "
1003    	0000000000000000000000000000000000000000000000000000000000000020
1004    	00000000000000000000000000000000000000000000000000000000ffffffff
1005    	0000000000000000000000000000000000000000000000000000000000000001
1006    	0000000000000000000000000000000000000000000000000000000000000002
1007        "
1008        );
1009        assert!(MyTy::abi_decode_sequence(&encoded).is_err());
1010    }
1011
1012    #[test]
1013    fn decode_dynamic_array_preallocation() {
1014        type MyTy = sol_data::Array<sol_data::Uint<32>>;
1015        let mut encoded = Vec::with_capacity(64);
1016        encoded.extend_from_slice(pad_usize(32).as_slice());
1017        encoded.extend_from_slice(pad_usize(usize::MAX).as_slice());
1018
1019        let err = MyTy::abi_decode_sequence(&encoded).unwrap_err();
1020        assert_eq!(err, Error::Overrun);
1021    }
1022
1023    #[test]
1024    fn decode_dynamic_array_of_zero_sized_type() {
1025        type MyTy = sol_data::Array<()>;
1026        let mut encoded = Vec::with_capacity(64);
1027        encoded.extend_from_slice(pad_usize(32).as_slice());
1028        encoded.extend_from_slice(pad_usize(2).as_slice());
1029
1030        assert_eq!(MyTy::abi_decode_sequence(&encoded).unwrap(), vec![(), ()]);
1031    }
1032
1033    #[test]
1034    fn decode_huge_dynamic_array_of_zero_sized_type_exceeds_memory_limit() {
1035        type MyTy = sol_data::Array<()>;
1036        let mut encoded = Vec::with_capacity(64);
1037        encoded.extend_from_slice(pad_usize(32).as_slice());
1038        encoded.extend_from_slice(pad_usize(u32::MAX as usize).as_slice());
1039
1040        assert_eq!(
1041            decode_sequence::<<MyTy as SolType>::Token<'_>>(&encoded),
1042            Err(Error::MemoryLimitExceeded(DEFAULT_MEMORY_LIMIT)),
1043        );
1044    }
1045
1046    #[test]
1047    fn decode_nested_dynamic_array_of_zero_sized_type() {
1048        type MyTy = sol_data::Array<sol_data::Array<()>>;
1049        let mut encoded = Vec::with_capacity(128);
1050        encoded.extend_from_slice(pad_usize(32).as_slice());
1051        encoded.extend_from_slice(pad_usize(1).as_slice());
1052        encoded.extend_from_slice(pad_usize(32).as_slice());
1053        encoded.extend_from_slice(pad_usize(2).as_slice());
1054
1055        assert_eq!(MyTy::abi_decode_sequence(&encoded).unwrap(), vec![vec![(), ()]]);
1056    }
1057
1058    #[test]
1059    fn decode_dynamic_array_of_multiword_static_type() {
1060        type MyTy = sol_data::Array<sol_data::FixedArray<sol_data::Uint<32>, 2>>;
1061        let mut encoded = Vec::with_capacity(96);
1062        encoded.extend_from_slice(pad_usize(32).as_slice());
1063        encoded.extend_from_slice(pad_usize(1).as_slice());
1064        // The fixed-array element requires two words, but only one is provided.
1065        encoded.extend_from_slice(pad_usize(1).as_slice());
1066
1067        let err = MyTy::abi_decode_sequence(&encoded).unwrap_err();
1068        assert_eq!(err, Error::Overrun);
1069    }
1070
1071    #[test]
1072    fn decode_dynamic_array_required_words_overflow() {
1073        type MyTy = sol_data::Array<sol_data::FixedArray<sol_data::Uint<32>, 2>>;
1074        let mut encoded = Vec::with_capacity(64);
1075        encoded.extend_from_slice(pad_usize(32).as_slice());
1076        encoded.extend_from_slice(pad_usize(usize::MAX).as_slice());
1077
1078        let err = MyTy::abi_decode_sequence(&encoded).unwrap_err();
1079        assert_eq!(err, Error::Overrun);
1080    }
1081
1082    #[test]
1083    fn decode_dynamic_array_of_dynamic_type() {
1084        type MyTy = sol_data::Array<sol_data::Array<sol_data::FixedArray<sol_data::Uint<32>, 3>>>;
1085        let mut encoded = Vec::with_capacity(128);
1086        encoded.extend_from_slice(pad_usize(32).as_slice());
1087        encoded.extend_from_slice(pad_usize(1).as_slice());
1088        // The dynamic element requires one offset word regardless of its inner static width.
1089        encoded.extend_from_slice(pad_usize(32).as_slice());
1090        // The nested array is empty, so no fixed-array data follows.
1091        encoded.extend_from_slice(pad_usize(0).as_slice());
1092
1093        let decoded = MyTy::abi_decode_sequence(&encoded).unwrap();
1094        assert_eq!(decoded.len(), 1);
1095        assert!(decoded[0].is_empty());
1096    }
1097
1098    #[test]
1099    fn decode_verify_addresses() {
1100        let input = hex!(
1101            "
1102    	0000000000000000000000000000000000000000000000000000000000012345
1103    	0000000000000000000000000000000000000000000000000000000000054321
1104    	"
1105        );
1106
1107        assert_eq!(
1108            sol_data::Address::abi_decode(&input).unwrap(),
1109            address!("0000000000000000000000000000000000012345")
1110        );
1111        assert!(<(sol_data::Address, sol_data::Address)>::abi_decode(&input).is_ok());
1112    }
1113
1114    #[test]
1115    fn decode_verify_bytes() {
1116        type MyTy2 = (sol_data::Address, sol_data::Address);
1117
1118        let input = hex!(
1119            "
1120    	0000000000000000000000001234500000000000000000000000000000012345
1121    	0000000000000000000000005432100000000000000000000000000000054321
1122    	"
1123        );
1124        assert!(MyTy2::abi_decode_params(&input).is_ok());
1125    }
1126
1127    #[test]
1128    fn signed_int_dirty_high_bytes() {
1129        type MyTy = sol_data::Int<8>;
1130
1131        let dirty_negative =
1132            hex!("f0ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff");
1133
1134        assert_eq!(MyTy::abi_decode(&dirty_negative).unwrap(), -1);
1135
1136        let dirty_positive =
1137            hex!("700000000000000000000000000000000000000000000000000000000000007f");
1138
1139        assert_eq!(MyTy::abi_decode(&dirty_positive).unwrap(), 127);
1140    }
1141
1142    // https://github.com/alloy-rs/core/issues/433
1143    #[test]
1144    fn fixed_before_dynamic() {
1145        sol! {
1146            #[derive(Debug, PartialEq, Eq)]
1147            struct Ty {
1148                bytes32[3] arr;
1149                bytes dyn;
1150            }
1151        }
1152
1153        let ty = Ty {
1154            arr: [[0x11u8; 32].into(), [0x22u8; 32].into(), [0x33u8; 32].into()],
1155            r#dyn: bytes![0x44u8; 4],
1156        };
1157        let encoded = hex!(
1158            "0000000000000000000000000000000000000000000000000000000000000020"
1159            "1111111111111111111111111111111111111111111111111111111111111111"
1160            "2222222222222222222222222222222222222222222222222222222222222222"
1161            "3333333333333333333333333333333333333333333333333333333333333333"
1162            "0000000000000000000000000000000000000000000000000000000000000080"
1163            "0000000000000000000000000000000000000000000000000000000000000004"
1164            "4444444400000000000000000000000000000000000000000000000000000000"
1165        );
1166        assert_eq!(hex::encode(ty.abi_encode()), hex::encode(encoded));
1167        assert_eq!(ty.abi_encoded_size(), encoded.len());
1168
1169        assert_eq!(<Ty as SolType>::abi_decode(&encoded).unwrap(), ty);
1170    }
1171
1172    #[test]
1173    fn dynarray_before_dynamic() {
1174        sol! {
1175            #[derive(Debug, PartialEq, Eq)]
1176            struct Ty {
1177                bytes[3] arr;
1178                bytes dyn;
1179            }
1180        }
1181
1182        let ty = Ty {
1183            arr: [bytes![0x11u8; 32], bytes![0x22u8; 32], bytes![0x33u8; 32]],
1184            r#dyn: bytes![0x44u8; 4],
1185        };
1186        let encoded = hex!(
1187            "0000000000000000000000000000000000000000000000000000000000000020" // struct offset
1188            "0000000000000000000000000000000000000000000000000000000000000040" // arr offset
1189            "0000000000000000000000000000000000000000000000000000000000000160" // dyn offset
1190            "0000000000000000000000000000000000000000000000000000000000000060" // arr[0] offset
1191            "00000000000000000000000000000000000000000000000000000000000000a0" // arr[1] offset
1192            "00000000000000000000000000000000000000000000000000000000000000e0" // arr[2] offset
1193            "0000000000000000000000000000000000000000000000000000000000000020" // arr[0]
1194            "1111111111111111111111111111111111111111111111111111111111111111"
1195            "0000000000000000000000000000000000000000000000000000000000000020" // arr[1]
1196            "2222222222222222222222222222222222222222222222222222222222222222"
1197            "0000000000000000000000000000000000000000000000000000000000000020" // arr[2]
1198            "3333333333333333333333333333333333333333333333333333333333333333"
1199            "0000000000000000000000000000000000000000000000000000000000000004" // dyn
1200            "4444444400000000000000000000000000000000000000000000000000000000"
1201        );
1202        assert_eq!(hex::encode(ty.abi_encode()), hex::encode(encoded));
1203        assert_eq!(ty.abi_encoded_size(), encoded.len());
1204
1205        assert_eq!(<Ty as SolType>::abi_decode(&encoded).unwrap(), ty);
1206    }
1207
1208    #[test]
1209    fn offset_overflow() {
1210        let encoded = hex!(
1211            "0000000000000000000000000000000000000000000000000000000000000020"
1212            "000000000000000000000000000000000000000000000000ffffffffffffffff"
1213            "0000000000000000000000000000000000000000000000000000000000000000"
1214        );
1215        let err = <sol_data::String as SolType>::abi_decode(&encoded).unwrap_err();
1216        assert_eq!(err, Error::Overrun);
1217    }
1218
1219    #[test]
1220    fn config_defaults_and_setters() {
1221        let mut config = AbiDecoderConfig::new();
1222        assert_eq!(config.get_recursion_limit(), 16);
1223        assert_eq!(config.get_memory_limit(), DEFAULT_MEMORY_LIMIT);
1224        assert!(!config.get_validate());
1225        assert!(!config.get_strict());
1226        assert!(!config.get_validate_allow_trailing_bytes());
1227
1228        config.set_recursion_limit(300);
1229        config.set_memory_limit(42);
1230        config.set_validate(true);
1231        config.set_strict(true);
1232        assert_eq!(config.get_recursion_limit(), 300);
1233        assert_eq!(config.get_memory_limit(), 42);
1234        assert!(config.get_validate());
1235        assert!(config.get_strict());
1236
1237        let config = AbiDecoderConfig::new().recursion_limit(400).memory_limit(24).strict(true);
1238        assert_eq!(config.get_recursion_limit(), 400);
1239        assert_eq!(config.get_memory_limit(), 24);
1240        assert!(config.get_validate());
1241        assert!(config.get_strict());
1242    }
1243
1244    #[test]
1245    fn validate_allow_trailing_bytes_config() {
1246        let mut config = AbiDecoderConfig::new().validate_allow_trailing_bytes(true);
1247        assert!(!config.get_validate());
1248        assert!(!config.get_strict());
1249        assert!(config.get_validate_allow_trailing_bytes());
1250
1251        config.set_validate_allow_trailing_bytes(false);
1252        assert!(!config.get_validate());
1253        assert!(!config.get_strict());
1254        assert!(!config.get_validate_allow_trailing_bytes());
1255
1256        config.set_strict(true);
1257        config.set_validate_allow_trailing_bytes(true);
1258        config.set_validate_allow_trailing_bytes(false);
1259        assert!(config.get_strict());
1260        assert!(config.get_validate());
1261
1262        config.set_strict(false);
1263        config.set_validate(true);
1264        config.set_validate_allow_trailing_bytes(true);
1265        assert!(!config.get_strict());
1266        assert!(config.get_validate());
1267        assert!(config.get_validate_allow_trailing_bytes());
1268        config.set_validate_allow_trailing_bytes(false);
1269        assert!(!config.get_strict());
1270        assert!(config.get_validate());
1271        assert!(!config.get_validate_allow_trailing_bytes());
1272    }
1273
1274    #[test]
1275    fn validate_allow_trailing_bytes_accepts_encoded_prefixes() {
1276        fn check<T: SolType>(value: &T::RustType)
1277        where
1278            T::RustType: PartialEq + core::fmt::Debug,
1279            for<'de> T::Token<'de>: TokenSeq<'de>,
1280        {
1281            type Encode<T> = fn(&<T as SolType>::RustType) -> Vec<u8>;
1282            type Decode<T> = fn(&[u8], AbiDecoderConfig) -> Result<<T as SolType>::RustType>;
1283            let codecs: [(Encode<T>, Decode<T>); 3] = [
1284                (T::abi_encode, T::abi_decode_with_config),
1285                (T::abi_encode_params, |data, config| {
1286                    T::abi_decode_params_with_config(data, config)
1287                }),
1288                (T::abi_encode_sequence, |data, config| {
1289                    T::abi_decode_sequence_with_config(data, config)
1290                }),
1291            ];
1292            for (encode, decode) in codecs {
1293                for suffix in [&[][..], &[0xff][..], &[0xaa; 32][..], &[0xbb; 33][..]] {
1294                    let mut encoded = encode(value);
1295                    encoded.extend_from_slice(suffix);
1296                    for config in [
1297                        AbiDecoderConfig::new().validate(true),
1298                        AbiDecoderConfig::new().validate(true).validate_allow_trailing_bytes(true),
1299                        AbiDecoderConfig::new().validate_allow_trailing_bytes(true),
1300                        AbiDecoderConfig::new().strict(true).validate_allow_trailing_bytes(true),
1301                        AbiDecoderConfig::new().validate_allow_trailing_bytes(true).strict(true),
1302                    ] {
1303                        assert_eq!(&decode(&encoded, config).unwrap(), value);
1304                    }
1305                    if !suffix.is_empty() {
1306                        assert_eq!(
1307                            decode(&encoded, AbiDecoderConfig::new().strict(true)),
1308                            Err(Error::ReserMismatch),
1309                        );
1310                    }
1311                }
1312            }
1313        }
1314
1315        check::<()>(&());
1316        check::<(sol_data::Uint<8>, sol_data::Bool)>(&(42, true));
1317        check::<(sol_data::Bytes, sol_data::Array<sol_data::String>)>(&(
1318            bytes!("1234"),
1319            vec!["hello".into(), alloc::string::String::new()],
1320        ));
1321        check::<(sol_data::Array<sol_data::Bytes>,)>(&(vec![],));
1322    }
1323
1324    #[test]
1325    fn validate_allow_trailing_bytes_keeps_other_checks() {
1326        let config = AbiDecoderConfig::new().strict(true).validate_allow_trailing_bytes(true);
1327        let value = bytes!("1122");
1328        let canonical = sol_data::Bytes::abi_encode(&value);
1329
1330        // A suffix cannot substitute for required padding or payload bytes.
1331        for len in [canonical.len() - 1, 65] {
1332            assert_eq!(
1333                sol_data::Bytes::abi_decode_with_config(&canonical[..len], config),
1334                Err(Error::Overrun),
1335            );
1336        }
1337        let mut dirty_padding = canonical.clone();
1338        dirty_padding[66] = 1;
1339        dirty_padding.push(0xff);
1340        assert_eq!(
1341            sol_data::Bytes::abi_decode_with_config(&dirty_padding, config),
1342            Err(Error::ReserMismatch),
1343        );
1344
1345        let mut gap = canonical;
1346        gap[31] = 64;
1347        gap.splice(32..32, [0; 32]);
1348        assert_eq!(
1349            sol_data::Bytes::abi_decode_with_config(&gap, config),
1350            Err(Error::ReserMismatch),
1351        );
1352
1353        type Pair = (sol_data::Bytes, sol_data::Bytes);
1354        let mut overlap = Pair::abi_encode_params(&(value.clone(), value));
1355        overlap[63] = overlap[31];
1356        assert_eq!(
1357            Pair::abi_decode_params_with_config(&overlap, config),
1358            Err(Error::ReserMismatch)
1359        );
1360
1361        let mut invalid_bool = Word::with_last_byte(2).to_vec();
1362        invalid_bool.push(0xff);
1363        assert!(sol_data::Bool::abi_decode_with_config(&invalid_bool, config).is_err());
1364
1365        let mut invalid_string = sol_data::Bytes::abi_encode(&bytes!("ff"));
1366        invalid_string.push(0xff);
1367        assert!(sol_data::String::abi_decode_with_config(&invalid_string, config).is_err());
1368    }
1369
1370    #[test]
1371    fn child_drop_keeps_the_furthest_strict_offset() {
1372        let decoder = Decoder::with_config(&[0; 192], AbiDecoderConfig::new().strict(true));
1373        let mut first = decoder.child(64).unwrap();
1374        let mut second = decoder.child(128).unwrap();
1375        first.take_word().unwrap();
1376        second.take_word().unwrap();
1377
1378        drop(second);
1379        drop(first);
1380
1381        assert_eq!(decoder.state.strict_next_offset().get(), 160);
1382    }
1383
1384    #[test]
1385    fn exhausted_decoder_debug_does_not_panic() {
1386        let mut decoder = Decoder::new(&[0; 32]);
1387        decoder.take_word().unwrap();
1388        assert!(!format!("{decoder:?}").is_empty());
1389    }
1390
1391    #[test]
1392    fn configured_decoder_validation() {
1393        let encoded = B256::repeat_byte(0x11);
1394        assert!(
1395            sol_data::Bool::abi_decode_with_config(encoded.as_slice(), AbiDecoderConfig::new())
1396                .is_ok()
1397        );
1398        assert!(
1399            sol_data::Bool::abi_decode_with_config(
1400                encoded.as_slice(),
1401                AbiDecoderConfig::new().validate(true),
1402            )
1403            .is_err()
1404        );
1405        assert!(
1406            sol_data::Bool::abi_decode_with_config(
1407                encoded.as_slice(),
1408                AbiDecoderConfig::new().strict(true),
1409            )
1410            .is_err()
1411        );
1412    }
1413
1414    #[test]
1415    fn strict_decoder_rejects_noncanonical_bool() {
1416        let encoded = Word::with_last_byte(2);
1417
1418        assert_eq!(sol_data::Bool::abi_decode(encoded.as_slice()), Ok(true));
1419        assert!(
1420            sol_data::Bool::abi_decode_with_config(
1421                encoded.as_slice(),
1422                AbiDecoderConfig::new().validate(true),
1423            )
1424            .is_err()
1425        );
1426        assert!(
1427            sol_data::Bool::abi_decode_with_config(
1428                encoded.as_slice(),
1429                AbiDecoderConfig::new().strict(true),
1430            )
1431            .is_err()
1432        );
1433    }
1434
1435    #[test]
1436    fn strict_decoder_rejects_overlapping_nested_offsets() {
1437        type Ty = sol_data::Array<sol_data::Bytes>;
1438
1439        let encoded = hex!(
1440            "0000000000000000000000000000000000000000000000000000000000000020" // array offset
1441            "0000000000000000000000000000000000000000000000000000000000000002" // array length
1442            "0000000000000000000000000000000000000000000000000000000000000040" // first bytes offset
1443            "0000000000000000000000000000000000000000000000000000000000000040" // second bytes offset
1444            "0000000000000000000000000000000000000000000000000000000000000001" // bytes length
1445            "1100000000000000000000000000000000000000000000000000000000000000"
1446        );
1447
1448        assert_eq!(Ty::abi_decode(&encoded).unwrap(), vec![bytes![0x11u8; 1], bytes![0x11u8; 1]]);
1449        assert_eq!(
1450            Ty::abi_decode_with_config(&encoded, AbiDecoderConfig::new().strict(true)),
1451            Err(Error::ReserMismatch),
1452        );
1453    }
1454
1455    #[test]
1456    fn strict_decoder_accepts_canonical_offsets() {
1457        type Ty = (sol_data::Bytes, sol_data::Bytes);
1458
1459        let value = (bytes![0x11u8, 0x22], bytes![0x33u8, 0x44]);
1460        let encoded = Ty::abi_encode_params(&value);
1461
1462        assert_eq!(
1463            Ty::abi_decode_params_with_config(&encoded, AbiDecoderConfig::new().strict(true)),
1464            Ok(value),
1465        );
1466    }
1467
1468    #[test]
1469    fn strict_decoder_accepts_static_composites_around_dynamic_fields() {
1470        type Uint = sol_data::Uint<256>;
1471        type StaticTuple = (Uint, Uint);
1472        type StaticArray = sol_data::FixedArray<StaticTuple, 2>;
1473        type Ty = (StaticTuple, sol_data::Bytes, StaticArray, sol_data::Bytes);
1474
1475        let value = (
1476            (U256::from(1), U256::from(2)),
1477            bytes![0x11u8; 1],
1478            [(U256::from(3), U256::from(4)), (U256::from(5), U256::from(6))],
1479            bytes![0x22u8; 1],
1480        );
1481        let encoded = Ty::abi_encode_params(&value);
1482
1483        assert_eq!(
1484            Ty::abi_decode_params_with_config(&encoded, AbiDecoderConfig::new().strict(true)),
1485            Ok(value),
1486        );
1487    }
1488
1489    #[test]
1490    fn strict_decoder_accepts_dynamic_array_sequence() {
1491        type Ty = sol_data::Array<sol_data::Bytes>;
1492
1493        let value = vec![bytes![0x11u8; 1], bytes!("2233")];
1494        let encoded = Ty::abi_encode(&value);
1495
1496        assert_eq!(
1497            Ty::abi_decode_sequence_with_config(&encoded, AbiDecoderConfig::new().strict(true)),
1498            Ok(value),
1499        );
1500    }
1501
1502    #[test]
1503    fn strict_decoder_accepts_dynamic_fixed_array_sequence() {
1504        type Ty = sol_data::FixedArray<sol_data::Bytes, 2>;
1505
1506        let value = [bytes![0x11u8; 1], bytes!("2233")];
1507        let encoded = Ty::abi_encode_sequence(&value);
1508
1509        assert_eq!(
1510            Ty::abi_decode_sequence_with_config(&encoded, AbiDecoderConfig::new().strict(true)),
1511            Ok(value),
1512        );
1513    }
1514
1515    #[test]
1516    fn strict_decoder_accepts_empty_dynamic_sequences() {
1517        type Fixed = sol_data::FixedArray<sol_data::Bytes, 0>;
1518
1519        let fixed: [alloy_primitives::Bytes; 0] = [];
1520        let encoded = Fixed::abi_encode(&fixed);
1521        assert_eq!(
1522            Fixed::abi_decode_with_config(&encoded, AbiDecoderConfig::new().strict(true)),
1523            Ok(fixed),
1524        );
1525
1526        type Dynamic = sol_data::Array<()>;
1527
1528        let dynamic = vec![];
1529        let encoded = Dynamic::abi_encode(&dynamic);
1530        assert_eq!(
1531            Dynamic::abi_decode_sequence_with_config(
1532                &encoded,
1533                AbiDecoderConfig::new().strict(true)
1534            ),
1535            Ok(dynamic),
1536        );
1537    }
1538
1539    #[test]
1540    fn strict_decoder_rejects_nonempty_zero_sized_dynamic_arrays() {
1541        type Ty = sol_data::Array<()>;
1542
1543        let encoded = hex!(
1544            "0000000000000000000000000000000000000000000000000000000000000020"
1545            "0000000000000000000000000000000000000000000000000000000000000001"
1546        );
1547
1548        assert_eq!(Ty::abi_decode_sequence(&encoded), Ok(vec![()]));
1549        assert_eq!(
1550            Ty::abi_decode_sequence_with_config(&encoded, AbiDecoderConfig::new().memory_limit(0)),
1551            Err(Error::MemoryLimitExceeded(0)),
1552        );
1553        assert_eq!(
1554            Ty::abi_decode_sequence_with_config(&encoded, AbiDecoderConfig::new().strict(true)),
1555            Err(Error::ReserMismatch),
1556        );
1557    }
1558
1559    #[test]
1560    fn strict_decoder_checks_dynamic_elements_before_reserving_the_outer_array() {
1561        type Ty = sol_data::Array<sol_data::FixedArray<sol_data::Bytes, 64>>;
1562
1563        let mut encoded = Vec::with_capacity(32 * 66);
1564        encoded.extend_from_slice(pad_usize(32).as_slice());
1565        encoded.extend_from_slice(pad_usize(1).as_slice());
1566        encoded.resize(32 * 66, 0);
1567
1568        assert_eq!(
1569            Ty::abi_decode_sequence_with_config(
1570                &encoded,
1571                AbiDecoderConfig::new().memory_limit(0).strict(true),
1572            ),
1573            Err(Error::ReserMismatch),
1574        );
1575    }
1576
1577    #[test]
1578    fn strict_decoder_rejects_gapped_offsets() {
1579        type Ty = (sol_data::String, sol_data::String);
1580
1581        let value = ("one".to_string(), "two".to_string());
1582        let mut encoded = Ty::abi_encode(&value);
1583        encoded[95] = 0xa0;
1584        encoded.splice(160..160, [0; 32]);
1585
1586        assert_eq!(Ty::abi_decode(&encoded), Ok(value));
1587        assert_eq!(
1588            Ty::abi_decode_with_config(&encoded, AbiDecoderConfig::new().strict(true)),
1589            Err(Error::ReserMismatch),
1590        );
1591    }
1592
1593    #[test]
1594    fn strict_decoder_rejects_trailing_data() {
1595        type Ty = (sol_data::Bytes, sol_data::Bytes);
1596
1597        let value = (bytes![0x11u8; 1], bytes![0x22u8; 1]);
1598        let mut encoded = Ty::abi_encode_params(&value);
1599        encoded.extend([0; 32]);
1600
1601        assert_eq!(Ty::abi_decode_params(&encoded), Ok(value));
1602        assert_eq!(
1603            Ty::abi_decode_params_with_config(&encoded, AbiDecoderConfig::new().strict(true)),
1604            Err(Error::ReserMismatch),
1605        );
1606    }
1607
1608    #[test]
1609    fn strict_decoder_accepts_nested_encoder_output() {
1610        type Ty = (
1611            sol_data::String,
1612            sol_data::Array<sol_data::Array<sol_data::Address>>,
1613            sol_data::Bytes,
1614        );
1615
1616        let value = (
1617            "strict".to_string(),
1618            vec![vec![Address::repeat_byte(0x11)], vec![Address::repeat_byte(0x22)]],
1619            bytes!("beef"),
1620        );
1621        let encoded = Ty::abi_encode(&value);
1622
1623        assert_eq!(
1624            Ty::abi_decode_with_config(&encoded, AbiDecoderConfig::new().strict(true)),
1625            Ok(value),
1626        );
1627    }
1628
1629    #[test]
1630    fn strict_decoder_rejects_nonzero_padding() {
1631        let encoded = hex!(
1632            "0000000000000000000000000000000000000000000000000000000000000020"
1633            "0000000000000000000000000000000000000000000000000000000000000001"
1634            "11ff000000000000000000000000000000000000000000000000000000000000"
1635        );
1636
1637        assert_eq!(sol_data::Bytes::abi_decode(&encoded).unwrap(), bytes![0x11u8; 1]);
1638        assert_eq!(
1639            sol_data::Bytes::abi_decode_with_config(&encoded, AbiDecoderConfig::new().strict(true)),
1640            Err(Error::ReserMismatch),
1641        );
1642    }
1643
1644    #[test]
1645    fn strict_decoder_rejects_overlapping_bytes_offsets() {
1646        type Ty = (sol_data::Bytes, sol_data::Bytes);
1647
1648        let encoded = hex!(
1649            "0000000000000000000000000000000000000000000000000000000000000040" // first bytes offset
1650            "0000000000000000000000000000000000000000000000000000000000000040" // second bytes offset
1651            "0000000000000000000000000000000000000000000000000000000000000003" // bytes length
1652            "1122330000000000000000000000000000000000000000000000000000000000"
1653        );
1654
1655        assert_eq!(
1656            Ty::abi_decode_params(&encoded).unwrap(),
1657            (bytes![0x11u8, 0x22, 0x33], bytes![0x11u8, 0x22, 0x33]),
1658        );
1659        assert_eq!(
1660            Ty::abi_decode_params_with_config(&encoded, AbiDecoderConfig::new().strict(true)),
1661            Err(Error::ReserMismatch),
1662        );
1663    }
1664
1665    #[test]
1666    fn strict_decoder_rejects_overlapping_dynamic_array_offsets() {
1667        type Ty = (sol_data::Array<sol_data::Uint<256>>, sol_data::Array<sol_data::Uint<256>>);
1668
1669        let encoded = hex!(
1670            "0000000000000000000000000000000000000000000000000000000000000040" // first array offset
1671            "0000000000000000000000000000000000000000000000000000000000000040" // second array offset
1672            "0000000000000000000000000000000000000000000000000000000000000002" // array length
1673            "0000000000000000000000000000000000000000000000000000000000000001"
1674            "0000000000000000000000000000000000000000000000000000000000000002"
1675        );
1676
1677        assert_eq!(
1678            Ty::abi_decode_params(&encoded).unwrap(),
1679            (vec![U256::from(1), U256::from(2)], vec![U256::from(1), U256::from(2)]),
1680        );
1681        assert_eq!(
1682            Ty::abi_decode_params_with_config(&encoded, AbiDecoderConfig::new().strict(true)),
1683            Err(Error::ReserMismatch),
1684        );
1685        assert_eq!(
1686            Ty::abi_decode_params_with_config(&encoded, AbiDecoderConfig::new().memory_limit(64)),
1687            Err(Error::MemoryLimitExceeded(64)),
1688        );
1689        assert_eq!(
1690            Ty::abi_decode_params_with_config(
1691                &encoded,
1692                AbiDecoderConfig::new().memory_limit(64).strict(true),
1693            ),
1694            Err(Error::ReserMismatch),
1695        );
1696    }
1697
1698    #[test]
1699    fn configured_decoder_enforces_memory_limit() {
1700        type Ty = sol_data::Array<sol_data::Uint<256>>;
1701
1702        let encoded = Ty::abi_encode(&vec![U256::ZERO]);
1703        let err = decode_sequence_with_config::<<Ty as SolType>::Token<'_>>(
1704            &encoded,
1705            AbiDecoderConfig::new().memory_limit(31),
1706        )
1707        .unwrap_err();
1708        assert_eq!(err, Error::MemoryLimitExceeded(31));
1709    }
1710
1711    #[test]
1712    fn direct_decoder_enforces_memory_limit() {
1713        type Ty = sol_data::Array<sol_data::Uint<256>>;
1714
1715        let encoded = Ty::abi_encode(&vec![U256::ZERO]);
1716        let mut decoder = Decoder::with_config(&encoded, AbiDecoderConfig::new().memory_limit(31));
1717        let err = decoder.decode::<<Ty as SolType>::Token<'_>>().unwrap_err();
1718        assert_eq!(err, Error::MemoryLimitExceeded(31));
1719    }
1720
1721    #[test]
1722    fn child_decoder_borrows_parent_state() {
1723        type Ty = sol_data::Array<sol_data::Uint<256>>;
1724
1725        let encoded = Ty::abi_encode(&vec![U256::ZERO]);
1726        let decoder = Decoder::with_config(&encoded, AbiDecoderConfig::new().memory_limit(31));
1727        let mut child = decoder.child(0).unwrap();
1728        let err = child.decode::<<Ty as SolType>::Token<'_>>().unwrap_err();
1729        assert_eq!(err, Error::MemoryLimitExceeded(31));
1730    }
1731
1732    #[test]
1733    fn configured_decoder_tracks_child_allocations() {
1734        type Ty = sol_data::Array<sol_data::Array<sol_data::Uint<256>>>;
1735
1736        let encoded = Ty::abi_encode(&vec![vec![U256::ZERO], vec![U256::ZERO]]);
1737        let err = decode_sequence_with_config::<<Ty as SolType>::Token<'_>>(
1738            &encoded,
1739            AbiDecoderConfig::new().memory_limit(100),
1740        )
1741        .unwrap_err();
1742        assert_eq!(err, Error::MemoryLimitExceeded(100));
1743    }
1744
1745    #[test]
1746    fn configured_decoder_tracks_recursive_allocations() {
1747        type Uint = sol_data::Uint<256>;
1748        type Inner = sol_data::Array<Uint>;
1749        type Middle = sol_data::Array<Inner>;
1750        type Ty = sol_data::Array<Middle>;
1751
1752        let value = vec![vec![vec![U256::ZERO]], vec![vec![U256::ZERO]]];
1753        let encoded = Ty::abi_encode(&value);
1754        let memory_used = 2 * core::mem::size_of::<<Middle as SolType>::Token<'_>>()
1755            + 2 * core::mem::size_of::<<Inner as SolType>::Token<'_>>()
1756            + 2 * core::mem::size_of::<<Uint as SolType>::Token<'_>>();
1757
1758        decode_sequence_with_config::<<Ty as SolType>::Token<'_>>(
1759            &encoded,
1760            AbiDecoderConfig::new().memory_limit(memory_used),
1761        )
1762        .unwrap();
1763        let err = decode_sequence_with_config::<<Ty as SolType>::Token<'_>>(
1764            &encoded,
1765            AbiDecoderConfig::new().memory_limit(memory_used - 1),
1766        )
1767        .unwrap_err();
1768        assert_eq!(err, Error::MemoryLimitExceeded(memory_used - 1));
1769    }
1770
1771    #[test]
1772    fn configured_decoder_tracks_aliased_tuple_allocations() {
1773        sol! {
1774            struct Rule {
1775                bytes4 selector;
1776                address[] recipients;
1777            }
1778
1779            struct Scope {
1780                address target;
1781                Rule[] rules;
1782            }
1783
1784            function apply(address account, Scope[] scopes);
1785        }
1786
1787        fn word(value: usize) -> [u8; 32] {
1788            let mut out = [0_u8; 32];
1789            out[24..].copy_from_slice(&(value as u64).to_be_bytes());
1790            out
1791        }
1792
1793        fn aliased_call_data(width: usize) -> Vec<u8> {
1794            let mut data = Vec::with_capacity(292 + 96 * width);
1795            data.extend(applyCall::SELECTOR);
1796
1797            data.extend(word(0));
1798            data.extend(word(64));
1799
1800            data.extend(word(width));
1801            for _ in 0..width {
1802                data.extend(word(width * 32));
1803            }
1804
1805            data.extend(word(1));
1806            data.extend(word(64));
1807
1808            data.extend(word(width));
1809            for _ in 0..width {
1810                data.extend(word(width * 32));
1811            }
1812
1813            let mut selector = [0_u8; 32];
1814            selector[..4].copy_from_slice(&[0xde, 0xad, 0xbe, 0xef]);
1815            data.extend(selector);
1816            data.extend(word(64));
1817
1818            data.extend(word(width));
1819            for i in 0..width {
1820                data.extend(word(i + 1));
1821            }
1822
1823            assert_eq!(data.len(), 292 + 96 * width);
1824            data
1825        }
1826
1827        type Address = sol_data::Address;
1828
1829        let width = 2_usize;
1830        let data = aliased_call_data(width);
1831        let memory_used = width * core::mem::size_of::<<Scope as SolType>::Token<'_>>()
1832            + width.pow(2) * core::mem::size_of::<<Rule as SolType>::Token<'_>>()
1833            + width.pow(3) * core::mem::size_of::<<Address as SolType>::Token<'_>>();
1834
1835        applyCall::abi_decode_with_config(&data, AbiDecoderConfig::new().memory_limit(memory_used))
1836            .unwrap();
1837        let err = match applyCall::abi_decode_with_config(
1838            &data,
1839            AbiDecoderConfig::new().memory_limit(memory_used - 1),
1840        ) {
1841            Ok(_) => panic!("decoding should exceed the memory limit"),
1842            Err(err) => err,
1843        };
1844        assert_eq!(err, Error::MemoryLimitExceeded(memory_used - 1));
1845
1846        let strict_memory_used = width
1847            * (core::mem::size_of::<<Scope as SolType>::Token<'_>>()
1848                + core::mem::size_of::<<Rule as SolType>::Token<'_>>()
1849                + core::mem::size_of::<<Address as SolType>::Token<'_>>());
1850        let err = match applyCall::abi_decode_with_config(
1851            &data,
1852            AbiDecoderConfig::new().memory_limit(strict_memory_used).strict(true),
1853        ) {
1854            Ok(_) => panic!("strict decoding should reject aliased offsets"),
1855            Err(err) => err,
1856        };
1857        assert_eq!(err, Error::ReserMismatch);
1858    }
1859
1860    #[test]
1861    fn configured_decoder_enforces_recursion_limit() {
1862        type Ty = sol_data::Array<sol_data::Uint<256>>;
1863
1864        let encoded = Ty::abi_encode(&vec![U256::ZERO]);
1865        let err = decode_sequence_with_config::<<Ty as SolType>::Token<'_>>(
1866            &encoded,
1867            AbiDecoderConfig::new().recursion_limit(0),
1868        )
1869        .unwrap_err();
1870        assert_eq!(err, Error::RecursionLimitExceeded(0));
1871    }
1872}