ssz/decode/
impls.rs

1use super::*;
2use crate::decode::try_from_iter::{TryCollect, TryFromIter};
3use alloy_primitives::{Address, Bloom, Bytes, FixedBytes, U128, U256};
4use core::num::NonZeroUsize;
5use itertools::process_results;
6use smallvec::SmallVec;
7use std::collections::{BTreeMap, BTreeSet};
8use std::iter::{self, FromIterator};
9use std::sync::Arc;
10
11macro_rules! impl_decodable_for_uint {
12    ($type: ident, $bit_size: expr) => {
13        impl Decode for $type {
14            #[inline(always)]
15            fn is_ssz_fixed_len() -> bool {
16                true
17            }
18
19            #[inline(always)]
20            fn ssz_fixed_len() -> usize {
21                $bit_size / 8
22            }
23
24            #[inline(always)]
25            fn from_ssz_bytes(bytes: &[u8]) -> Result<Self, DecodeError> {
26                let len = bytes.len();
27                let expected = <Self as Decode>::ssz_fixed_len();
28
29                if len != expected {
30                    Err(DecodeError::InvalidByteLength { len, expected })
31                } else {
32                    let mut array: [u8; $bit_size / 8] = std::default::Default::default();
33                    array.clone_from_slice(bytes);
34
35                    Ok(Self::from_le_bytes(array))
36                }
37            }
38        }
39    };
40}
41
42impl_decodable_for_uint!(u8, 8);
43impl_decodable_for_uint!(u16, 16);
44impl_decodable_for_uint!(u32, 32);
45impl_decodable_for_uint!(u64, 64);
46impl_decodable_for_uint!(u128, 128);
47
48#[cfg(target_pointer_width = "32")]
49impl_decodable_for_uint!(usize, 32);
50
51#[cfg(target_pointer_width = "64")]
52impl_decodable_for_uint!(usize, 64);
53
54macro_rules! impl_decode_for_tuples {
55    ($(
56        $Tuple:ident {
57            $(($idx:tt) -> $T:ident)+
58        }
59    )+) => {
60        $(
61            impl<$($T: Decode),+> Decode for ($($T,)+) {
62                fn is_ssz_fixed_len() -> bool {
63                    $(
64                        <$T as Decode>::is_ssz_fixed_len() &&
65                    )*
66                        true
67                }
68
69                fn ssz_fixed_len() -> usize {
70                    if <Self as Decode>::is_ssz_fixed_len() {
71                        $(
72                            <$T as Decode>::ssz_fixed_len() +
73                        )*
74                            0
75                    } else {
76                        BYTES_PER_LENGTH_OFFSET
77                    }
78                }
79
80                fn from_ssz_bytes(bytes: &[u8]) -> Result<Self, DecodeError> {
81                    let mut builder = SszDecoderBuilder::new(bytes);
82
83                    $(
84                        builder.register_type::<$T>()?;
85                    )*
86
87                    let mut decoder = builder.build()?;
88
89                    Ok(($(
90                            decoder.decode_next::<$T>()?,
91                        )*
92                    ))
93                }
94            }
95        )+
96    }
97}
98
99impl_decode_for_tuples! {
100    Tuple2 {
101        (0) -> A
102        (1) -> B
103    }
104    Tuple3 {
105        (0) -> A
106        (1) -> B
107        (2) -> C
108    }
109    Tuple4 {
110        (0) -> A
111        (1) -> B
112        (2) -> C
113        (3) -> D
114    }
115    Tuple5 {
116        (0) -> A
117        (1) -> B
118        (2) -> C
119        (3) -> D
120        (4) -> E
121    }
122    Tuple6 {
123        (0) -> A
124        (1) -> B
125        (2) -> C
126        (3) -> D
127        (4) -> E
128        (5) -> F
129    }
130    Tuple7 {
131        (0) -> A
132        (1) -> B
133        (2) -> C
134        (3) -> D
135        (4) -> E
136        (5) -> F
137        (6) -> G
138    }
139    Tuple8 {
140        (0) -> A
141        (1) -> B
142        (2) -> C
143        (3) -> D
144        (4) -> E
145        (5) -> F
146        (6) -> G
147        (7) -> H
148    }
149    Tuple9 {
150        (0) -> A
151        (1) -> B
152        (2) -> C
153        (3) -> D
154        (4) -> E
155        (5) -> F
156        (6) -> G
157        (7) -> H
158        (8) -> I
159    }
160    Tuple10 {
161        (0) -> A
162        (1) -> B
163        (2) -> C
164        (3) -> D
165        (4) -> E
166        (5) -> F
167        (6) -> G
168        (7) -> H
169        (8) -> I
170        (9) -> J
171    }
172    Tuple11 {
173        (0) -> A
174        (1) -> B
175        (2) -> C
176        (3) -> D
177        (4) -> E
178        (5) -> F
179        (6) -> G
180        (7) -> H
181        (8) -> I
182        (9) -> J
183        (10) -> K
184    }
185    Tuple12 {
186        (0) -> A
187        (1) -> B
188        (2) -> C
189        (3) -> D
190        (4) -> E
191        (5) -> F
192        (6) -> G
193        (7) -> H
194        (8) -> I
195        (9) -> J
196        (10) -> K
197        (11) -> L
198    }
199}
200
201impl Decode for bool {
202    fn is_ssz_fixed_len() -> bool {
203        true
204    }
205
206    fn ssz_fixed_len() -> usize {
207        1
208    }
209
210    fn from_ssz_bytes(bytes: &[u8]) -> Result<Self, DecodeError> {
211        let len = bytes.len();
212        let expected = <Self as Decode>::ssz_fixed_len();
213
214        if len != expected {
215            Err(DecodeError::InvalidByteLength { len, expected })
216        } else {
217            match bytes[0] {
218                0b0000_0000 => Ok(false),
219                0b0000_0001 => Ok(true),
220                _ => Err(DecodeError::BytesInvalid(format!(
221                    "Out-of-range for boolean: {}",
222                    bytes[0]
223                ))),
224            }
225        }
226    }
227}
228
229impl Decode for NonZeroUsize {
230    fn is_ssz_fixed_len() -> bool {
231        <usize as Decode>::is_ssz_fixed_len()
232    }
233
234    fn ssz_fixed_len() -> usize {
235        <usize as Decode>::ssz_fixed_len()
236    }
237
238    fn from_ssz_bytes(bytes: &[u8]) -> Result<Self, DecodeError> {
239        let x = usize::from_ssz_bytes(bytes)?;
240
241        if x == 0 {
242            Err(DecodeError::BytesInvalid(
243                "NonZeroUsize cannot be zero.".to_string(),
244            ))
245        } else {
246            // `unwrap` is safe here as `NonZeroUsize::new()` succeeds if `x > 0` and this path
247            // never executes when `x == 0`.
248            Ok(NonZeroUsize::new(x).unwrap())
249        }
250    }
251}
252
253impl<T: Decode> Decode for Option<T> {
254    fn is_ssz_fixed_len() -> bool {
255        false
256    }
257    fn from_ssz_bytes(bytes: &[u8]) -> Result<Self, DecodeError> {
258        let (selector, body) = split_union_bytes(bytes)?;
259        match selector.into() {
260            0u8 => Ok(None),
261            1u8 => <T as Decode>::from_ssz_bytes(body).map(Option::Some),
262            other => Err(DecodeError::UnionSelectorInvalid(other)),
263        }
264    }
265}
266
267impl<T: Decode> Decode for Arc<T> {
268    fn is_ssz_fixed_len() -> bool {
269        T::is_ssz_fixed_len()
270    }
271
272    fn ssz_fixed_len() -> usize {
273        T::ssz_fixed_len()
274    }
275
276    fn from_ssz_bytes(bytes: &[u8]) -> Result<Self, DecodeError> {
277        T::from_ssz_bytes(bytes).map(Arc::new)
278    }
279}
280
281impl Decode for Address {
282    fn is_ssz_fixed_len() -> bool {
283        true
284    }
285
286    fn ssz_fixed_len() -> usize {
287        20
288    }
289
290    fn from_ssz_bytes(bytes: &[u8]) -> Result<Self, DecodeError> {
291        let len = bytes.len();
292        let expected = <Self as Decode>::ssz_fixed_len();
293
294        if len != expected {
295            Err(DecodeError::InvalidByteLength { len, expected })
296        } else {
297            Ok(Self::from_slice(bytes))
298        }
299    }
300}
301
302impl<const N: usize> Decode for FixedBytes<N> {
303    fn is_ssz_fixed_len() -> bool {
304        true
305    }
306
307    fn ssz_fixed_len() -> usize {
308        N
309    }
310
311    fn from_ssz_bytes(bytes: &[u8]) -> Result<Self, DecodeError> {
312        if bytes.len() != N {
313            return Err(DecodeError::InvalidByteLength {
314                len: bytes.len(),
315                expected: N,
316            });
317        }
318
319        let mut fixed_array = [0u8; N];
320        fixed_array.copy_from_slice(bytes);
321
322        Ok(Self(fixed_array))
323    }
324}
325
326impl Decode for Bloom {
327    fn is_ssz_fixed_len() -> bool {
328        true
329    }
330
331    fn ssz_fixed_len() -> usize {
332        256
333    }
334
335    fn from_ssz_bytes(bytes: &[u8]) -> Result<Self, DecodeError> {
336        let len = bytes.len();
337        let expected = <Self as Decode>::ssz_fixed_len();
338
339        if len != expected {
340            Err(DecodeError::InvalidByteLength { len, expected })
341        } else {
342            Ok(Self::from_slice(bytes))
343        }
344    }
345}
346
347impl Decode for U256 {
348    fn is_ssz_fixed_len() -> bool {
349        true
350    }
351
352    fn ssz_fixed_len() -> usize {
353        32
354    }
355
356    fn from_ssz_bytes(bytes: &[u8]) -> Result<Self, DecodeError> {
357        let len = bytes.len();
358        let expected = <Self as Decode>::ssz_fixed_len();
359
360        if len != expected {
361            Err(DecodeError::InvalidByteLength { len, expected })
362        } else {
363            Ok(U256::from_le_slice(bytes))
364        }
365    }
366}
367
368impl Decode for Bytes {
369    #[inline]
370    fn is_ssz_fixed_len() -> bool {
371        false
372    }
373
374    #[inline]
375    fn from_ssz_bytes(bytes: &[u8]) -> Result<Self, DecodeError> {
376        Ok(bytes.to_vec().into())
377    }
378}
379
380impl Decode for U128 {
381    fn is_ssz_fixed_len() -> bool {
382        true
383    }
384
385    fn ssz_fixed_len() -> usize {
386        16
387    }
388
389    fn from_ssz_bytes(bytes: &[u8]) -> Result<Self, DecodeError> {
390        let len = bytes.len();
391        let expected = <Self as Decode>::ssz_fixed_len();
392
393        if len != expected {
394            Err(DecodeError::InvalidByteLength { len, expected })
395        } else {
396            Ok(U128::from_le_slice(bytes))
397        }
398    }
399}
400
401impl<const N: usize> Decode for [u8; N] {
402    fn is_ssz_fixed_len() -> bool {
403        true
404    }
405
406    fn ssz_fixed_len() -> usize {
407        N
408    }
409
410    fn from_ssz_bytes(bytes: &[u8]) -> Result<Self, DecodeError> {
411        let len = bytes.len();
412        let expected = <Self as Decode>::ssz_fixed_len();
413
414        if len != expected {
415            Err(DecodeError::InvalidByteLength { len, expected })
416        } else {
417            let mut array: [u8; N] = [0; N];
418            array.copy_from_slice(bytes);
419
420            Ok(array)
421        }
422    }
423}
424
425impl<T: Decode> Decode for Vec<T> {
426    fn is_ssz_fixed_len() -> bool {
427        false
428    }
429
430    fn from_ssz_bytes(bytes: &[u8]) -> Result<Self, DecodeError> {
431        if bytes.is_empty() {
432            Ok(vec![])
433        } else if T::is_ssz_fixed_len() {
434            bytes
435                .chunks(T::ssz_fixed_len())
436                .map(T::from_ssz_bytes)
437                .collect()
438        } else {
439            decode_list_of_variable_length_items(bytes, None)
440        }
441    }
442}
443
444impl<T: Decode, const N: usize> Decode for SmallVec<[T; N]> {
445    fn is_ssz_fixed_len() -> bool {
446        false
447    }
448
449    fn from_ssz_bytes(bytes: &[u8]) -> Result<Self, DecodeError> {
450        if bytes.is_empty() {
451            Ok(SmallVec::new())
452        } else if T::is_ssz_fixed_len() {
453            bytes
454                .chunks(T::ssz_fixed_len())
455                .map(T::from_ssz_bytes)
456                .collect()
457        } else {
458            decode_list_of_variable_length_items(bytes, None)
459        }
460    }
461}
462
463impl<K, V> Decode for BTreeMap<K, V>
464where
465    K: Decode + Ord,
466    V: Decode,
467{
468    fn is_ssz_fixed_len() -> bool {
469        false
470    }
471
472    fn from_ssz_bytes(bytes: &[u8]) -> Result<Self, DecodeError> {
473        if bytes.is_empty() {
474            Ok(Self::from_iter(iter::empty()))
475        } else if <(K, V)>::is_ssz_fixed_len() {
476            bytes
477                .chunks(<(K, V)>::ssz_fixed_len())
478                .map(<(K, V)>::from_ssz_bytes)
479                .collect()
480        } else {
481            decode_list_of_variable_length_items(bytes, None)
482        }
483    }
484}
485
486impl<T> Decode for BTreeSet<T>
487where
488    T: Decode + Ord,
489{
490    fn is_ssz_fixed_len() -> bool {
491        false
492    }
493
494    fn from_ssz_bytes(bytes: &[u8]) -> Result<Self, DecodeError> {
495        if bytes.is_empty() {
496            Ok(Self::from_iter(iter::empty()))
497        } else if T::is_ssz_fixed_len() {
498            bytes
499                .chunks(T::ssz_fixed_len())
500                .map(T::from_ssz_bytes)
501                .collect()
502        } else {
503            decode_list_of_variable_length_items(bytes, None)
504        }
505    }
506}
507
508/// Decodes `bytes` as if it were a list of variable-length items.
509///
510/// The `ssz::SszDecoder` can also perform this functionality, however this function is
511/// significantly faster as it is optimized to read same-typed items whilst `ssz::SszDecoder`
512/// supports reading items of differing types.
513pub fn decode_list_of_variable_length_items<T: Decode, Container: TryFromIter<T>>(
514    bytes: &[u8],
515    max_len: Option<usize>,
516) -> Result<Container, DecodeError> {
517    if bytes.is_empty() {
518        return Container::try_from_iter(iter::empty()).map_err(|e| {
519            DecodeError::BytesInvalid(format!("Error trying to collect empty list: {:?}", e))
520        });
521    }
522
523    let first_offset = read_offset(bytes)?;
524    sanitize_offset(first_offset, None, bytes.len(), Some(first_offset))?;
525
526    if first_offset % BYTES_PER_LENGTH_OFFSET != 0 || first_offset < BYTES_PER_LENGTH_OFFSET {
527        return Err(DecodeError::InvalidListFixedBytesLen(first_offset));
528    }
529
530    let num_items = first_offset / BYTES_PER_LENGTH_OFFSET;
531
532    if max_len.is_some_and(|max| num_items > max) {
533        return Err(DecodeError::BytesInvalid(format!(
534            "Variable length list of {} items exceeds maximum of {:?}",
535            num_items, max_len
536        )));
537    }
538
539    let mut offset = first_offset;
540    process_results(
541        (1..=num_items).map(|i| {
542            let slice_option = if i == num_items {
543                bytes.get(offset..)
544            } else {
545                let start = offset;
546
547                let next_offset = read_offset(&bytes[(i * BYTES_PER_LENGTH_OFFSET)..])?;
548                offset =
549                    sanitize_offset(next_offset, Some(offset), bytes.len(), Some(first_offset))?;
550
551                bytes.get(start..offset)
552            };
553
554            let slice = slice_option.ok_or(DecodeError::OutOfBoundsByte { i: offset })?;
555            T::from_ssz_bytes(slice)
556        }),
557        |iter| iter.try_collect(),
558    )?
559    .map_err(|e| DecodeError::BytesInvalid(format!("Error collecting into container: {:?}", e)))
560}
561
562#[cfg(test)]
563mod tests {
564    use super::*;
565    use alloy_primitives::B256;
566
567    // Note: decoding of valid bytes is generally tested "indirectly" in the `/tests` dir, by
568    // encoding then decoding the element.
569
570    #[test]
571    fn invalid_u8_array_4() {
572        assert_eq!(
573            <[u8; 4]>::from_ssz_bytes(&[0; 3]),
574            Err(DecodeError::InvalidByteLength {
575                len: 3,
576                expected: 4
577            })
578        );
579
580        assert_eq!(
581            <[u8; 4]>::from_ssz_bytes(&[0; 5]),
582            Err(DecodeError::InvalidByteLength {
583                len: 5,
584                expected: 4
585            })
586        );
587    }
588
589    #[test]
590    fn invalid_bool() {
591        assert_eq!(
592            bool::from_ssz_bytes(&[0; 2]),
593            Err(DecodeError::InvalidByteLength {
594                len: 2,
595                expected: 1
596            })
597        );
598
599        assert_eq!(
600            bool::from_ssz_bytes(&[]),
601            Err(DecodeError::InvalidByteLength {
602                len: 0,
603                expected: 1
604            })
605        );
606
607        if let Err(DecodeError::BytesInvalid(_)) = bool::from_ssz_bytes(&[2]) {
608            // Success.
609        } else {
610            panic!("Did not return error on invalid bool val")
611        }
612    }
613
614    #[test]
615    fn invalid_b256() {
616        assert_eq!(
617            B256::from_ssz_bytes(&[0; 33]),
618            Err(DecodeError::InvalidByteLength {
619                len: 33,
620                expected: 32
621            })
622        );
623
624        assert_eq!(
625            B256::from_ssz_bytes(&[0; 31]),
626            Err(DecodeError::InvalidByteLength {
627                len: 31,
628                expected: 32
629            })
630        );
631    }
632
633    #[test]
634    fn empty_list() {
635        let vec: Vec<Vec<u16>> = vec![];
636        let bytes = vec.as_ssz_bytes();
637        assert!(bytes.is_empty());
638        assert_eq!(Vec::from_ssz_bytes(&bytes), Ok(vec),);
639    }
640
641    #[test]
642    fn first_length_points_backwards() {
643        assert_eq!(
644            <Vec<Vec<u16>>>::from_ssz_bytes(&[0, 0, 0, 0]),
645            Err(DecodeError::InvalidListFixedBytesLen(0))
646        );
647
648        assert_eq!(
649            <Vec<Vec<u16>>>::from_ssz_bytes(&[1, 0, 0, 0]),
650            Err(DecodeError::InvalidListFixedBytesLen(1))
651        );
652
653        assert_eq!(
654            <Vec<Vec<u16>>>::from_ssz_bytes(&[2, 0, 0, 0]),
655            Err(DecodeError::InvalidListFixedBytesLen(2))
656        );
657
658        assert_eq!(
659            <Vec<Vec<u16>>>::from_ssz_bytes(&[3, 0, 0, 0]),
660            Err(DecodeError::InvalidListFixedBytesLen(3))
661        );
662    }
663
664    #[test]
665    fn lengths_are_decreasing() {
666        assert_eq!(
667            <Vec<Vec<u16>>>::from_ssz_bytes(&[12, 0, 0, 0, 14, 0, 0, 0, 12, 0, 0, 0, 1, 0, 1, 0]),
668            Err(DecodeError::OffsetsAreDecreasing(12))
669        );
670    }
671
672    #[test]
673    fn awkward_fixed_length_portion() {
674        assert_eq!(
675            <Vec<Vec<u16>>>::from_ssz_bytes(&[10, 0, 0, 0, 10, 0, 0, 0, 0, 0]),
676            Err(DecodeError::InvalidListFixedBytesLen(10))
677        );
678    }
679
680    #[test]
681    fn length_out_of_bounds() {
682        assert_eq!(
683            <Vec<Vec<u16>>>::from_ssz_bytes(&[5, 0, 0, 0]),
684            Err(DecodeError::OffsetOutOfBounds(5))
685        );
686        assert_eq!(
687            <Vec<Vec<u16>>>::from_ssz_bytes(&[8, 0, 0, 0, 9, 0, 0, 0]),
688            Err(DecodeError::OffsetOutOfBounds(9))
689        );
690        assert_eq!(
691            <Vec<Vec<u16>>>::from_ssz_bytes(&[8, 0, 0, 0, 16, 0, 0, 0]),
692            Err(DecodeError::OffsetOutOfBounds(16))
693        );
694    }
695
696    #[test]
697    fn vec_of_vec_of_u16() {
698        assert_eq!(
699            <Vec<Vec<u16>>>::from_ssz_bytes(&[4, 0, 0, 0]),
700            Ok(vec![vec![]])
701        );
702
703        assert_eq!(
704            <Vec<u16>>::from_ssz_bytes(&[0, 0, 1, 0, 2, 0, 3, 0]),
705            Ok(vec![0, 1, 2, 3])
706        );
707        assert_eq!(<u16>::from_ssz_bytes(&[16, 0]), Ok(16));
708        assert_eq!(<u16>::from_ssz_bytes(&[0, 1]), Ok(256));
709        assert_eq!(<u16>::from_ssz_bytes(&[255, 255]), Ok(65535));
710
711        assert_eq!(
712            <u16>::from_ssz_bytes(&[255]),
713            Err(DecodeError::InvalidByteLength {
714                len: 1,
715                expected: 2
716            })
717        );
718
719        assert_eq!(
720            <u16>::from_ssz_bytes(&[]),
721            Err(DecodeError::InvalidByteLength {
722                len: 0,
723                expected: 2
724            })
725        );
726
727        assert_eq!(
728            <u16>::from_ssz_bytes(&[0, 1, 2]),
729            Err(DecodeError::InvalidByteLength {
730                len: 3,
731                expected: 2
732            })
733        );
734    }
735
736    #[test]
737    fn vec_of_u16() {
738        assert_eq!(<Vec<u16>>::from_ssz_bytes(&[0, 0, 0, 0]), Ok(vec![0, 0]));
739        assert_eq!(
740            <Vec<u16>>::from_ssz_bytes(&[0, 0, 1, 0, 2, 0, 3, 0]),
741            Ok(vec![0, 1, 2, 3])
742        );
743        assert_eq!(<u16>::from_ssz_bytes(&[16, 0]), Ok(16));
744        assert_eq!(<u16>::from_ssz_bytes(&[0, 1]), Ok(256));
745        assert_eq!(<u16>::from_ssz_bytes(&[255, 255]), Ok(65535));
746
747        assert_eq!(
748            <u16>::from_ssz_bytes(&[255]),
749            Err(DecodeError::InvalidByteLength {
750                len: 1,
751                expected: 2
752            })
753        );
754
755        assert_eq!(
756            <u16>::from_ssz_bytes(&[]),
757            Err(DecodeError::InvalidByteLength {
758                len: 0,
759                expected: 2
760            })
761        );
762
763        assert_eq!(
764            <u16>::from_ssz_bytes(&[0, 1, 2]),
765            Err(DecodeError::InvalidByteLength {
766                len: 3,
767                expected: 2
768            })
769        );
770    }
771
772    #[test]
773    fn u16() {
774        assert_eq!(<u16>::from_ssz_bytes(&[0, 0]), Ok(0));
775        assert_eq!(<u16>::from_ssz_bytes(&[16, 0]), Ok(16));
776        assert_eq!(<u16>::from_ssz_bytes(&[0, 1]), Ok(256));
777        assert_eq!(<u16>::from_ssz_bytes(&[255, 255]), Ok(65535));
778
779        assert_eq!(
780            <u16>::from_ssz_bytes(&[255]),
781            Err(DecodeError::InvalidByteLength {
782                len: 1,
783                expected: 2
784            })
785        );
786
787        assert_eq!(
788            <u16>::from_ssz_bytes(&[]),
789            Err(DecodeError::InvalidByteLength {
790                len: 0,
791                expected: 2
792            })
793        );
794
795        assert_eq!(
796            <u16>::from_ssz_bytes(&[0, 1, 2]),
797            Err(DecodeError::InvalidByteLength {
798                len: 3,
799                expected: 2
800            })
801        );
802    }
803
804    #[test]
805    fn tuple() {
806        assert_eq!(<(u16, u16)>::from_ssz_bytes(&[0, 0, 0, 0]), Ok((0, 0)));
807        assert_eq!(<(u16, u16)>::from_ssz_bytes(&[16, 0, 17, 0]), Ok((16, 17)));
808        assert_eq!(<(u16, u16)>::from_ssz_bytes(&[0, 1, 2, 0]), Ok((256, 2)));
809        assert_eq!(
810            <(u16, u16)>::from_ssz_bytes(&[255, 255, 0, 0]),
811            Ok((65535, 0))
812        );
813    }
814
815    #[test]
816    fn vec_of_u128_roundtrip() {
817        let values = vec![
818            vec![0u128, 55u128, u128::MAX, u128::MAX - 3],
819            vec![],
820            vec![u128::MAX],
821            vec![u32::MAX as u128],
822            vec![0, 0, 0, 0],
823            vec![0, 0, 0, 0, 0, 0],
824        ];
825        for vec in values {
826            assert_eq!(
827                Vec::<u128>::from_ssz_bytes(&vec.as_ssz_bytes()).unwrap(),
828                vec
829            );
830        }
831    }
832}