Skip to main content

tycho_types/abi/value/
de.rs

1use std::collections::BTreeMap;
2use std::num::NonZeroU8;
3
4use anyhow::Result;
5use bytes::Bytes;
6use num_bigint::{BigInt, BigUint};
7
8use crate::abi::error::AbiError;
9use crate::abi::{
10    AbiHeader, AbiHeaderType, AbiType, AbiValue, AbiVersion, NamedAbiType, NamedAbiValue,
11    PlainAbiType, PlainAbiValue,
12};
13use crate::cell::{Cell, CellSlice, Load, MAX_BIT_LEN, MAX_REF_COUNT};
14use crate::dict::{self, RawDict};
15use crate::error::Error;
16use crate::models::{AnyAddr, IntAddr, StdAddr};
17use crate::num::Tokens;
18
19impl NamedAbiValue {
20    /// Loads exactly one tuple from the specified slice requiring it to be fully consumed.
21    ///
22    /// Use [`NamedAbiValue::load_tuple_partial`] if you allow an ABI type to be a prefix.
23    pub fn load_tuple(
24        items: &[NamedAbiType],
25        version: AbiVersion,
26        slice: &mut CellSlice,
27    ) -> Result<Vec<Self>> {
28        let result = ok!(Self::load_tuple_ext(items, version, true, false, slice));
29        ok!(AbiValue::check_remaining(slice, false));
30        Ok(result)
31    }
32
33    /// Loads a tuple from the specified slice.
34    pub fn load_tuple_partial(
35        items: &[NamedAbiType],
36        version: AbiVersion,
37        slice: &mut CellSlice,
38    ) -> Result<Vec<Self>> {
39        Self::load_tuple_ext(items, version, true, true, slice)
40    }
41
42    /// Loads a tuple from the specified slice with explicit decoder params.
43    ///
44    /// NOTE: this method does not check the remaining bits and refs in the root slice.
45    pub fn load_tuple_ext(
46        items: &[NamedAbiType],
47        version: AbiVersion,
48        last: bool,
49        allow_partial: bool,
50        slice: &mut CellSlice,
51    ) -> Result<Vec<Self>> {
52        let mut result = Vec::with_capacity(items.len());
53        let items_len = items.len();
54        for (i, item) in items.iter().enumerate() {
55            let last = last && i + 1 == items_len;
56            result.push(ok!(Self::load_ext(
57                item,
58                version,
59                last,
60                allow_partial,
61                slice
62            )));
63        }
64        Ok(result)
65    }
66
67    /// Loads exactly one ABI value from the specified slice requiring it to be fully consumed.
68    ///
69    /// Use [`NamedAbiValue::load_partial`] if you allow an ABI type to be a prefix.
70    pub fn load(ty: &NamedAbiType, version: AbiVersion, slice: &mut CellSlice) -> Result<Self> {
71        let res = ok!(Self::load_ext(ty, version, true, false, slice));
72        ok!(AbiValue::check_remaining(slice, false));
73        Ok(res)
74    }
75
76    /// Loads an ABI value from the specified slice.
77    pub fn load_partial(
78        ty: &NamedAbiType,
79        version: AbiVersion,
80        slice: &mut CellSlice,
81    ) -> Result<Self> {
82        Self::load_ext(ty, version, true, true, slice)
83    }
84
85    /// Loads an ABI value from the specified slice with explicit decoder params.
86    ///
87    /// NOTE: this method does not check the remaining bits and refs in the root slice.
88    pub fn load_ext(
89        ty: &NamedAbiType,
90        version: AbiVersion,
91        last: bool,
92        allow_partial: bool,
93        slice: &mut CellSlice,
94    ) -> Result<Self> {
95        Ok(Self {
96            value: ok!(AbiValue::load_ext(
97                &ty.ty,
98                version,
99                last,
100                allow_partial,
101                slice
102            )),
103            name: ty.name.clone(),
104        })
105    }
106}
107
108impl AbiValue {
109    /// Checks whether the slice is empty and raises an error if we didn't expect it to be empty.
110    pub fn check_remaining(slice: &mut CellSlice, allow_partial: bool) -> Result<()> {
111        anyhow::ensure!(
112            allow_partial || slice.is_data_empty() && slice.is_refs_empty(),
113            AbiError::IncompleteDeserialization
114        );
115        Ok(())
116    }
117
118    /// Loads exactly one unnamed tuple from the specified slice requiring it to be fully consumed.
119    ///
120    /// Use [`AbiValue::load_tuple_partial`] if you allow an ABI type to be a prefix.
121    pub fn load_tuple(
122        types: &[AbiType],
123        version: AbiVersion,
124        slice: &mut CellSlice,
125    ) -> Result<Vec<Self>> {
126        let res = ok!(Self::load_tuple_ext(types, version, true, false, slice));
127        ok!(Self::check_remaining(slice, false));
128        Ok(res)
129    }
130
131    /// Loads an unnamed tuple from the specified slice.
132    pub fn load_tuple_partial(
133        types: &[AbiType],
134        version: AbiVersion,
135        slice: &mut CellSlice,
136    ) -> Result<Vec<Self>> {
137        Self::load_tuple_ext(types, version, true, true, slice)
138    }
139
140    /// Loads an unnamed tuple from the specified slice with explicit decoder params.
141    ///
142    /// NOTE: this method does not check the remaining bits and refs in the root slice.
143    pub fn load_tuple_ext(
144        types: &[AbiType],
145        version: AbiVersion,
146        last: bool,
147        allow_partial: bool,
148        slice: &mut CellSlice,
149    ) -> Result<Vec<Self>> {
150        let mut result = Vec::with_capacity(types.len());
151        let types_len = types.len();
152        for (i, ty) in types.iter().enumerate() {
153            let last = last && i + 1 == types_len;
154            result.push(ok!(Self::load_ext(ty, version, last, allow_partial, slice)));
155        }
156        Ok(result)
157    }
158
159    /// Loads exactly one ABI value from the specified slice requiring it to be fully consumed.
160    ///
161    /// Use [`AbiValue::load_partial`] if you allow an ABI type to be a prefix.
162    pub fn load(ty: &AbiType, version: AbiVersion, slice: &mut CellSlice) -> Result<Self> {
163        let res = ok!(Self::load_ext(ty, version, true, false, slice));
164        ok!(Self::check_remaining(slice, false));
165        Ok(res)
166    }
167
168    /// Loads an ABI value from the specified slice.
169    pub fn load_partial(ty: &AbiType, version: AbiVersion, slice: &mut CellSlice) -> Result<Self> {
170        Self::load_ext(ty, version, true, true, slice)
171    }
172
173    /// Loads an ABI value from the specified slice with explicit decoder params.
174    ///
175    /// NOTE: this method does not check the remaining bits and refs in the root slice.
176    pub fn load_ext(
177        ty: &AbiType,
178        version: AbiVersion,
179        last: bool,
180        allow_partial: bool,
181        slice: &mut CellSlice,
182    ) -> Result<Self> {
183        match ty {
184            AbiType::Uint(bits) => load_uint(*bits, slice).map(|value| Self::Uint(*bits, value)),
185            AbiType::Int(bits) => load_int(*bits, slice).map(|value| Self::Int(*bits, value)),
186            AbiType::VarUint(size) => {
187                load_varuint(*size, slice).map(|value| Self::VarUint(*size, value))
188            }
189            AbiType::VarInt(size) => {
190                load_varint(*size, slice).map(|value| Self::VarInt(*size, value))
191            }
192            AbiType::Bool => {
193                ok!(preload_bits(1, slice));
194                Ok(Self::Bool(slice.load_bit()?))
195            }
196            AbiType::Cell => load_cell(version, last, slice).map(Self::Cell),
197            AbiType::Address => {
198                ok!(preload_bits(1, slice));
199                Ok(Self::Address(AnyAddr::load_from(slice).map(Box::new)?))
200            }
201            AbiType::AddressStd => {
202                ok!(preload_bits(1, slice));
203                Ok(Self::AddressStd(match AnyAddr::load_from(slice)? {
204                    AnyAddr::None => None,
205                    AnyAddr::Std(addr) => Some(Box::new(addr)),
206                    _ => anyhow::bail!("Expected StdAddr or None"),
207                }))
208            }
209            AbiType::Bytes => load_bytes(version, last, slice).map(Self::Bytes),
210            AbiType::FixedBytes(len) => {
211                load_fixed_bytes(*len, version, last, slice).map(Self::FixedBytes)
212            }
213            AbiType::String => load_string(version, last, slice).map(Self::String),
214            AbiType::Token => {
215                ok!(preload_bits(1, slice));
216                Ok(Self::Token(Tokens::load_from(slice)?))
217            }
218            AbiType::Tuple(items) => {
219                let values = ok!(NamedAbiValue::load_tuple_ext(
220                    items,
221                    version,
222                    last,
223                    allow_partial,
224                    slice
225                ));
226                Ok(Self::Tuple(values))
227            }
228            AbiType::Array(ty) => load_array(ty, version, allow_partial, slice)
229                .map(|values| Self::Array(ty.clone(), values)),
230            AbiType::FixedArray(ty, len) => {
231                load_fixed_array(ty, *len, version, allow_partial, slice)
232                    .map(|values| Self::FixedArray(ty.clone(), values))
233            }
234            AbiType::Map(key_ty, value_ty) => {
235                load_map(*key_ty, value_ty, version, allow_partial, slice)
236                    .map(|value| Self::Map(*key_ty, value_ty.clone(), value))
237            }
238            AbiType::Optional(ty) => load_optional(ty, version, last, allow_partial, slice)
239                .map(|value| Self::Optional(ty.clone(), value)),
240            AbiType::Ref(ty) => load_ref(ty, version, last, allow_partial, slice).map(Self::Ref),
241        }
242    }
243}
244
245impl PlainAbiValue {
246    /// Loads a corresponding value from the slice.
247    pub fn load(ty: PlainAbiType, slice: &mut CellSlice) -> Result<Self, Error> {
248        match ty {
249            PlainAbiType::Uint(bits) => {
250                load_uint_plain(bits, slice).map(|value| Self::Uint(bits, value))
251            }
252            PlainAbiType::Int(bits) => {
253                load_int_plain(bits, slice).map(|value| Self::Int(bits, value))
254            }
255            PlainAbiType::Bool => slice.load_bit().map(Self::Bool),
256            PlainAbiType::Address => IntAddr::load_from(slice).map(Box::new).map(Self::Address),
257            PlainAbiType::AddressStd => StdAddr::load_from(slice)
258                .map(Box::new)
259                .map(Self::AddressStd),
260            PlainAbiType::FixedBytes(bytes) => {
261                let Ok(bits) = u16::try_from(bytes.saturating_mul(8)) else {
262                    return Err(Error::IntOverflow);
263                };
264                let mut buffer = [0u8; 128];
265                let res = slice.load_raw(&mut buffer, bits)?;
266                Ok(Self::FixedBytes(Bytes::from(res.to_vec())))
267            }
268        }
269    }
270}
271
272impl AbiHeader {
273    /// Skips all specified headers in slice.
274    pub fn skip_all(headers: &[AbiHeaderType], slice: &mut CellSlice) -> Result<()> {
275        for header in headers {
276            ok!(Self::skip(*header, slice))
277        }
278        Ok(())
279    }
280
281    /// Loads and ignores a corresponding value from the slice.
282    pub fn skip(ty: AbiHeaderType, slice: &mut CellSlice) -> Result<()> {
283        match ty {
284            AbiHeaderType::Time => {
285                ok!(preload_bits(64, slice));
286                slice.skip_first(64, 0)?;
287            }
288            AbiHeaderType::Expire => {
289                ok!(preload_bits(32, slice));
290                slice.skip_first(32, 0)?;
291            }
292            AbiHeaderType::PublicKey => {
293                ok!(preload_bits(1, slice));
294                if slice.load_bit()? {
295                    ok!(preload_bits(256, slice));
296                    slice.skip_first(256, 0)?;
297                }
298            }
299        }
300        Ok(())
301    }
302
303    /// Loads a corresponding value from the slice.
304    pub fn load(ty: AbiHeaderType, slice: &mut CellSlice) -> Result<Self> {
305        Ok(match ty {
306            AbiHeaderType::Time => {
307                ok!(preload_bits(64, slice));
308                Self::Time(slice.load_u64()?)
309            }
310            AbiHeaderType::Expire => {
311                ok!(preload_bits(32, slice));
312                Self::Expire(slice.load_u32()?)
313            }
314            AbiHeaderType::PublicKey => {
315                ok!(preload_bits(1, slice));
316                Self::PublicKey(if slice.load_bit()? {
317                    ok!(preload_bits(256, slice));
318                    let Ok(pubkey) =
319                        ed25519_dalek::VerifyingKey::from_bytes(slice.load_u256()?.as_array())
320                    else {
321                        anyhow::bail!(Error::InvalidPublicKey);
322                    };
323                    Some(Box::new(pubkey))
324                } else {
325                    None
326                })
327            }
328        })
329    }
330}
331
332fn preload_bits(bits: u16, slice: &mut CellSlice) -> Result<()> {
333    if bits == 0 {
334        return Ok(());
335    }
336
337    let remaining_bits = slice.size_bits();
338    if remaining_bits == 0 {
339        let first_ref = slice.load_reference_as_slice()?;
340
341        // TODO: why `allow_partial` is not used here in a reference impl?
342        anyhow::ensure!(slice.is_refs_empty(), AbiError::IncompleteDeserialization);
343
344        *slice = first_ref;
345    } else if remaining_bits < bits {
346        anyhow::bail!(Error::CellUnderflow);
347    }
348
349    Ok(())
350}
351
352fn load_uint(bits: u16, slice: &mut CellSlice) -> Result<BigUint> {
353    ok!(preload_bits(bits, slice));
354    load_uint_plain(bits, slice).map_err(From::from)
355}
356
357fn load_int(bits: u16, slice: &mut CellSlice) -> Result<BigInt> {
358    ok!(preload_bits(bits, slice));
359    load_int_plain(bits, slice).map_err(From::from)
360}
361
362fn load_uint_plain(bits: u16, slice: &mut CellSlice) -> Result<BigUint, Error> {
363    match bits {
364        0 => Ok(BigUint::default()),
365        1..=64 => slice.load_uint(bits).map(BigUint::from),
366        _ => {
367            let rem = bits % 8;
368            let mut buffer = vec![0u8; bits.div_ceil(8) as usize];
369            slice.load_raw(&mut buffer, bits)?;
370
371            buffer.reverse();
372            let mut int = BigUint::from_bytes_le(&buffer);
373            if rem != 0 {
374                int >>= 8 - rem;
375            }
376            Ok(int)
377        }
378    }
379}
380
381fn load_int_plain(bits: u16, slice: &mut CellSlice) -> Result<BigInt, Error> {
382    match bits {
383        0 => Ok(BigInt::default()),
384        1..=64 => slice.load_uint(bits).map(|mut int| {
385            if bits < 64 {
386                // Clone sign bit into all high bits
387                int |= ((int >> (bits - 1)) * u64::MAX) << (bits - 1);
388            }
389            BigInt::from(int as i64)
390        }),
391        _ => {
392            let rem = bits % 8;
393            let mut buffer = vec![0u8; bits.div_ceil(8) as usize];
394            slice.load_raw(&mut buffer, bits)?;
395
396            buffer.reverse();
397            let mut int = BigInt::from_signed_bytes_le(&buffer);
398            if rem != 0 {
399                int >>= 8 - rem;
400            }
401            Ok(int)
402        }
403    }
404}
405
406fn load_varuint(size: NonZeroU8, slice: &mut CellSlice) -> Result<BigUint> {
407    let bytes = ok!(load_varuint_raw(size, slice));
408    Ok(BigUint::from_bytes_le(&bytes))
409}
410
411fn load_varint(size: NonZeroU8, slice: &mut CellSlice) -> Result<BigInt> {
412    // TODO: manually use `twos_complement_le` to prevent useless cloning in `from_signed_bytes_le`
413    let bytes = ok!(load_varuint_raw(size, slice));
414    Ok(BigInt::from_signed_bytes_le(&bytes))
415}
416
417/// Loads a varuint as bytes in LE (!) order.
418fn load_varuint_raw(size: NonZeroU8, slice: &mut CellSlice) -> Result<Vec<u8>> {
419    let value_size = size.get() - 1;
420
421    let len_bits = (8 - value_size.leading_zeros()) as u16;
422    ok!(preload_bits(len_bits, slice));
423
424    let value_bytes = slice.load_small_uint(len_bits)? as usize;
425    let value_bits = (value_bytes * 8) as u16;
426    ok!(preload_bits(value_bits, slice));
427
428    let mut bytes = vec![0u8; value_bytes];
429    slice.load_raw(&mut bytes, value_bits)?;
430
431    // NOTE: reverse and use `from_bytes_le` to prevent useless cloning in `from_bytes_be`
432    bytes.reverse();
433    Ok(bytes)
434}
435
436fn load_cell(version: AbiVersion, last: bool, slice: &mut CellSlice) -> Result<Cell> {
437    if slice.size_refs() == 1
438        && (version.major == 1 && slice.cell().reference_count() as usize == MAX_REF_COUNT
439            || version.major > 1 && !last && slice.size_bits() == 0)
440    {
441        *slice = slice.load_reference_as_slice()?;
442    }
443    slice.load_reference_cloned().map_err(From::from)
444}
445
446fn load_bytes_raw(version: AbiVersion, last: bool, slice: &mut CellSlice) -> Result<Vec<u8>> {
447    let cell = ok!(load_cell(version, last, slice));
448    let mut cell = cell.as_ref();
449
450    let mut bytes = Vec::new();
451    loop {
452        anyhow::ensure!(cell.bit_len() % 8 == 0, AbiError::ExpectedCellWithBytes);
453        bytes.extend_from_slice(cell.data());
454
455        match cell.reference(0) {
456            Some(child) => cell = child,
457            None => break Ok(bytes),
458        };
459    }
460}
461
462fn load_bytes(version: AbiVersion, last: bool, slice: &mut CellSlice) -> Result<Bytes> {
463    load_bytes_raw(version, last, slice).map(Bytes::from)
464}
465
466fn load_fixed_bytes(
467    len: usize,
468    version: AbiVersion,
469    last: bool,
470    slice: &mut CellSlice,
471) -> Result<Bytes> {
472    if version >= AbiVersion::V2_4 {
473        let bit_len = len as u16 * 8;
474        ok!(preload_bits(bit_len, slice));
475        let mut buffer = vec![0u8; len];
476        let result = slice.load_raw(buffer.as_mut_slice(), bit_len)?;
477        Ok(Bytes::copy_from_slice(result))
478    } else {
479        let bytes = ok!(load_bytes(version, last, slice));
480        anyhow::ensure!(bytes.len() == len, AbiError::BytesSizeMismatch {
481            expected: len,
482            len: bytes.len()
483        });
484        Ok(bytes)
485    }
486}
487
488fn load_string(version: AbiVersion, last: bool, slice: &mut CellSlice) -> Result<String> {
489    let bytes = ok!(load_bytes_raw(version, last, slice));
490    match String::from_utf8(bytes) {
491        Ok(str) => Ok(str),
492        Err(e) => Err(AbiError::InvalidString(e.utf8_error()).into()),
493    }
494}
495
496fn load_array_raw(
497    ty: &AbiType,
498    len: usize,
499    version: AbiVersion,
500    allow_partial: bool,
501    slice: &mut CellSlice,
502) -> Result<Vec<AbiValue>> {
503    ok!(preload_bits(1, slice));
504    let dict = RawDict::<32>::load_from(slice)?;
505
506    let mut result = Vec::with_capacity(len);
507    for value in dict.values().take(len) {
508        let slice = &mut value?;
509        let value = ok!(AbiValue::load_ext(ty, version, true, allow_partial, slice));
510        ok!(AbiValue::check_remaining(slice, allow_partial));
511        result.push(value);
512    }
513
514    Ok(result)
515}
516
517fn load_array(
518    ty: &AbiType,
519    version: AbiVersion,
520    allow_partial: bool,
521    slice: &mut CellSlice,
522) -> Result<Vec<AbiValue>> {
523    ok!(preload_bits(32, slice));
524    let len = slice.load_u32()?;
525    load_array_raw(ty, len as usize, version, allow_partial, slice)
526}
527
528fn load_fixed_array(
529    ty: &AbiType,
530    len: usize,
531    version: AbiVersion,
532    allow_partial: bool,
533    slice: &mut CellSlice,
534) -> Result<Vec<AbiValue>> {
535    let values = ok!(load_array_raw(ty, len, version, allow_partial, slice));
536    anyhow::ensure!(values.len() == len, AbiError::ArraySizeMismatch {
537        expected: len,
538        len: values.len()
539    });
540    Ok(values)
541}
542
543fn load_map(
544    key_ty: PlainAbiType,
545    value_ty: &AbiType,
546    version: AbiVersion,
547    allow_partial: bool,
548    slice: &mut CellSlice,
549) -> Result<BTreeMap<PlainAbiValue, AbiValue>> {
550    ok!(preload_bits(1, slice));
551
552    let key_bits = key_ty.key_bits();
553    let dict = Option::<Cell>::load_from(slice)?;
554
555    let mut result = BTreeMap::new();
556    for entry in dict::RawIter::new(&dict, key_bits) {
557        let (key, mut slice) = entry?;
558        let key = PlainAbiValue::load(key_ty, &mut key.as_data_slice())?;
559        let value = ok!(AbiValue::load_ext(
560            value_ty,
561            version,
562            true,
563            allow_partial,
564            &mut slice
565        ));
566        result.insert(key, value);
567    }
568
569    Ok(result)
570}
571
572fn load_optional(
573    ty: &AbiType,
574    version: AbiVersion,
575    last: bool,
576    allow_partial: bool,
577    slice: &mut CellSlice,
578) -> Result<Option<Box<AbiValue>>> {
579    ok!(preload_bits(1, slice));
580
581    if !slice.load_bit()? {
582        return Ok(None);
583    }
584
585    let ty_size = ty.max_size(version);
586    if ty_size.bit_count < MAX_BIT_LEN as u64 && ty_size.cell_count < MAX_REF_COUNT as u64 {
587        let value = ok!(AbiValue::load_ext(ty, version, last, allow_partial, slice));
588        Ok(Some(Box::new(value)))
589    } else {
590        let cell = ok!(load_cell(version, last, slice));
591        let slice = &mut cell.as_slice()?;
592        let value = ok!(AbiValue::load_ext(ty, version, true, allow_partial, slice));
593        ok!(AbiValue::check_remaining(slice, allow_partial));
594        Ok(Some(Box::new(value)))
595    }
596}
597
598fn load_ref(
599    ty: &AbiType,
600    version: AbiVersion,
601    last: bool,
602    allow_partial: bool,
603    slice: &mut CellSlice,
604) -> Result<Box<AbiValue>> {
605    let cell = ok!(load_cell(version, last, slice));
606    let slice = &mut cell.as_slice()?;
607    let value = ok!(AbiValue::load_ext(ty, version, true, allow_partial, slice));
608    ok!(AbiValue::check_remaining(slice, allow_partial));
609    Ok(Box::new(value))
610}
611
612#[cfg(test)]
613mod tests {
614    use std::sync::Arc;
615
616    use super::*;
617    use crate::boc::Boc;
618    use crate::dict::Dict;
619    use crate::models::{StdAddr, VarAddr};
620    use crate::num::{Uint9, VarUint24, VarUint56};
621    use crate::prelude::{CellBuilder, CellFamily, HashBytes, Store};
622
623    trait BuildCell {
624        fn build_cell(&self) -> Result<Cell>;
625    }
626
627    impl<T: Store> BuildCell for T {
628        fn build_cell(&self) -> Result<Cell> {
629            CellBuilder::build_from(self).map_err(From::from)
630        }
631    }
632
633    impl BuildCell for &str {
634        fn build_cell(&self) -> Result<Cell> {
635            Boc::decode_base64(self).map_err(From::from)
636        }
637    }
638
639    fn load_simple<T>(version: AbiVersion, boc: T, expected: AbiValue) -> Result<()>
640    where
641        T: BuildCell,
642    {
643        let cell = boc.build_cell()?;
644        let ty = expected.get_type();
645        assert_eq!(
646            AbiValue::load(&ty, version, &mut cell.as_slice()?)?,
647            expected
648        );
649        Ok(())
650    }
651
652    fn load_tuple<T>(version: AbiVersion, boc: T, expected: &[AbiValue]) -> Result<()>
653    where
654        T: BuildCell,
655    {
656        let cell = boc.build_cell()?;
657        let ty = expected.iter().map(AbiValue::get_type).collect::<Vec<_>>();
658        assert_eq!(
659            AbiValue::load_tuple(&ty, version, &mut cell.as_slice()?)?,
660            expected
661        );
662        Ok(())
663    }
664
665    macro_rules! assert_basic_err {
666        ($expr:expr, $err:expr) => {{
667            match $expr {
668                Ok(_) => panic!("Expected basic error: {:?}, got success", $err),
669                Err(e) => {
670                    if let Some(e) = e.downcast_ref::<Error>() {
671                        assert_eq!(e, &($err));
672                    } else {
673                        panic!("Unexpected error: {e:?}");
674                    }
675                }
676            }
677        }};
678    }
679
680    macro_rules! assert_abi_err {
681        ($expr:expr, $err:expr) => {{
682            match $expr {
683                Ok(_) => panic!("Expected ABI error: {:?}, got success", $err),
684                Err(e) => {
685                    if let Some(e) = e.downcast_ref::<AbiError>() {
686                        assert_eq!(e, &($err));
687                    } else {
688                        panic!("Unexpected error: {e:?}");
689                    }
690                }
691            }
692        }};
693    }
694
695    const VX_X: [AbiVersion; 5] = [
696        AbiVersion::V1_0,
697        AbiVersion::V2_0,
698        AbiVersion::V2_1,
699        AbiVersion::V2_2,
700        AbiVersion::V2_3,
701    ];
702    const V2_X: [AbiVersion; 4] = [
703        AbiVersion::V2_0,
704        AbiVersion::V2_1,
705        AbiVersion::V2_2,
706        AbiVersion::V2_3,
707    ];
708
709    #[test]
710    fn failed_decode() -> Result<()> {
711        for v in VX_X {
712            assert_basic_err!(
713                load_simple(v, false, AbiValue::uint(32, 0u32)),
714                Error::CellUnderflow
715            );
716
717            assert_abi_err!(
718                load_simple(v, u64::MAX, AbiValue::uint(32, 0u32)),
719                AbiError::IncompleteDeserialization
720            );
721
722            assert_abi_err!(
723                load_tuple(v, u64::MAX, &[AbiValue::uint(32, u32::MAX)]),
724                AbiError::IncompleteDeserialization
725            );
726        }
727
728        Ok(())
729    }
730
731    #[test]
732    fn decode_int() -> Result<()> {
733        macro_rules! define_tests {
734            ($v:ident, { $($abi:ident($bits:literal) => [$($expr:expr),*$(,)?]),*$(,)? }) => {$(
735                $(load_simple($v, $expr, AbiValue::$abi($bits, $expr))?;)*
736            )*};
737        }
738
739        for v in VX_X {
740            define_tests!(v, {
741                uint(8) => [0u8, 123u8, u8::MAX],
742                uint(16) => [0u16, 1234u16, u16::MAX],
743                uint(32) => [0u32, 123456u32, u32::MAX],
744                uint(64) => [0u64, 123456789u64, u64::MAX],
745                uint(128) => [0u128, 123456789123123123123u128, u128::MAX],
746
747                int(8) => [0i8, 123i8, i8::MIN, i8::MAX],
748                int(16) => [0i16, 1234i16, i16::MIN, i16::MAX],
749                int(32) => [0i32, 123456i32, i32::MIN, i32::MAX],
750                int(64) => [0i64, 123456789i64, i64::MIN, i64::MAX],
751                int(128) => [0i128, 123456789123123123123i128, i128::MIN, i128::MAX],
752            });
753        }
754
755        Ok(())
756    }
757
758    #[test]
759    fn decode_varint() -> Result<()> {
760        for v in VX_X {
761            println!("ABIv{v}");
762            load_simple(v, VarUint24::ZERO, AbiValue::varuint(4, 0u32))?;
763            load_simple(v, VarUint24::MAX, AbiValue::varuint(4, u32::MAX >> 8))?;
764            load_simple(v, VarUint24::new(123321), AbiValue::varuint(4, 123321u32))?;
765
766            load_simple(v, VarUint56::ZERO, AbiValue::varuint(8, 0u32))?;
767            load_simple(v, VarUint56::MAX, AbiValue::varuint(8, u64::MAX >> 8))?;
768            load_simple(
769                v,
770                VarUint56::new(1233213213123123),
771                AbiValue::varuint(8, 1233213213123123u64),
772            )?;
773
774            load_simple(
775                v,
776                "te6ccgEBAQEABgAABzAeG5g=",
777                AbiValue::varuint(16, 123321u32),
778            )?;
779            load_simple(v, "te6ccgEBAQEABgAABzAeG5g=", AbiValue::varint(16, 123321))?;
780
781            load_simple(v, Tokens::ZERO, AbiValue::varuint(16, 0u32))?;
782            load_simple(v, Tokens::ZERO, AbiValue::Token(Tokens::ZERO))?;
783
784            let mut prev_value = 0;
785            for byte in 0..15 {
786                let value = (0xffu128 << (byte * 8)) | prev_value;
787                prev_value = value;
788                load_simple(v, Tokens::new(value), AbiValue::varuint(16, value))?;
789                load_simple(v, Tokens::new(value), AbiValue::Token(Tokens::new(value)))?;
790            }
791        }
792
793        Ok(())
794    }
795
796    #[test]
797    fn decode_bool() -> Result<()> {
798        for v in VX_X {
799            println!("ABIv{v}");
800            load_simple(v, false, AbiValue::Bool(false))?;
801            load_simple(v, true, AbiValue::Bool(true))?;
802        }
803        Ok(())
804    }
805
806    #[test]
807    fn decode_cell() -> Result<()> {
808        // ABI v1
809        {
810            load_simple(
811                AbiVersion::V1_0,
812                "te6ccgEBAgEABQABAAEAAA==", // one ref with empty cell
813                AbiValue::Cell(Cell::empty_cell()),
814            )?;
815
816            // 4 refs with empty cells
817            let cell = Boc::decode_base64("te6ccgEBAgEACAAEAAEBAQEAAA==")?;
818            let slice = &mut cell.as_slice()?;
819            slice.skip_first(0, 3)?;
820
821            assert_basic_err!(
822                AbiValue::load(&AbiType::Cell, AbiVersion::V1_0, slice),
823                Error::CellUnderflow
824            );
825
826            // 3 refs with empty cells + last ref with a cell with 1 ref
827            let cell = Boc::decode_base64("te6ccgEBAwEACwAEAAICAgEBAAIAAA==")?;
828            let slice = &mut cell.as_slice()?;
829            slice.skip_first(0, 3)?;
830
831            assert_eq!(
832                AbiValue::load(&AbiType::Cell, AbiVersion::V1_0, slice)?,
833                AbiValue::Cell(Cell::empty_cell())
834            );
835        }
836
837        for v in V2_X {
838            println!("ABIv{v}");
839            load_simple(
840                v,
841                "te6ccgEBAgEABQABAAEAAA==", // one ref with empty cell
842                AbiValue::Cell(Cell::empty_cell()),
843            )?;
844
845            // 4 refs with empty cells
846            let cell = Boc::decode_base64("te6ccgEBAgEACAAEAAEBAQEAAA==")?;
847            let slice = &mut cell.as_slice()?;
848            slice.skip_first(0, 3)?;
849
850            assert_eq!(
851                AbiValue::load(&AbiType::Cell, v, slice)?,
852                AbiValue::Cell(Cell::empty_cell())
853            );
854        }
855
856        Ok(())
857    }
858
859    #[test]
860    fn decode_address() -> Result<()> {
861        for v in VX_X {
862            println!("ABIv{v}");
863            let addr: StdAddr = StdAddr::from((0i8, [0xffu8; 32]));
864            load_simple(
865                v,
866                addr.clone(),
867                AbiValue::Address(Box::new(AnyAddr::Std(addr))),
868            )?;
869
870            let addr: VarAddr = VarAddr {
871                address_len: Uint9::new(10 * 8),
872                anycast: None,
873                workchain: 123456,
874                address: vec![0xffu8; 10],
875            };
876            load_simple(
877                v,
878                addr.clone(),
879                AbiValue::Address(Box::new(AnyAddr::Var(addr))),
880            )?;
881        }
882
883        Ok(())
884    }
885
886    #[test]
887    fn decode_bytes() -> Result<()> {
888        for v in VX_X {
889            println!("ABIv{v}");
890            for len in 0..20 {
891                let mut bytes = vec![0xffu8; 1usize << len];
892                bytes[0] = 0x55; // mark start
893                let bytes = Bytes::from(bytes);
894                let serialized = AbiValue::Bytes(bytes.clone()).make_cell(v)?;
895
896                load_simple(v, serialized.clone(), AbiValue::Bytes(bytes.clone()))?;
897                load_simple(v, serialized.clone(), AbiValue::FixedBytes(bytes.clone()))?;
898
899                let original = bytes.len();
900                assert_abi_err!(
901                    load_simple(
902                        v,
903                        serialized.clone(),
904                        AbiValue::FixedBytes(bytes.slice(..original / 2))
905                    ),
906                    AbiError::BytesSizeMismatch {
907                        expected: original / 2,
908                        len: original
909                    }
910                )
911            }
912        }
913
914        Ok(())
915    }
916
917    #[test]
918    fn decode_string() -> Result<()> {
919        for v in VX_X {
920            println!("ABIv{v}");
921            for len in 0..20 {
922                let mut bytes = vec![b'a'; 1usize << len];
923                bytes[0] = b'f'; // mark start
924                let string = String::from_utf8(bytes)?;
925
926                let serialized = AbiValue::String(string.clone()).make_cell(v)?;
927                load_simple(v, serialized.clone(), AbiValue::String(string))?;
928            }
929        }
930
931        Ok(())
932    }
933
934    #[test]
935    fn decode_nested_simple_tuple() -> Result<()> {
936        let cell = {
937            let mut builder = CellBuilder::new();
938            builder.store_u32(0)?;
939            builder.store_reference(Cell::empty_cell())?;
940            builder.store_bit_zero()?;
941            builder.store_u8(-15_i8 as _)?;
942            builder.store_u16(-9845_i16 as _)?;
943            builder.store_u32(-1_i32 as _)?;
944            builder.store_u64(12345678_i64 as _)?;
945            builder.store_u128(-12345678_i128 as _)?;
946            builder.store_u8(255)?;
947            builder.store_u16(0)?;
948            builder.store_u32(256)?;
949            builder.store_u64(123)?;
950            builder.store_u128(1234567890)?;
951            builder.build()?
952        };
953
954        let value = AbiValue::unnamed_tuple([
955            AbiValue::uint(32, 0u32),
956            AbiValue::Cell(Cell::empty_cell()),
957            AbiValue::Bool(false),
958            AbiValue::unnamed_tuple([
959                AbiValue::int(8, -15),
960                AbiValue::int(16, -9845),
961                AbiValue::unnamed_tuple([
962                    AbiValue::int(32, -1),
963                    AbiValue::int(64, 12345678),
964                    AbiValue::int(128, -12345678),
965                ]),
966            ]),
967            AbiValue::unnamed_tuple([
968                AbiValue::uint(8, 255_u8),
969                AbiValue::uint(16, 0_u16),
970                AbiValue::unnamed_tuple([
971                    AbiValue::uint(32, 256_u32),
972                    AbiValue::uint(64, 123_u64),
973                    AbiValue::uint(128, 1234567890_u128),
974                ]),
975            ]),
976        ]);
977
978        for v in VX_X {
979            println!("ABIv{v}");
980            load_simple(v, cell.clone(), value.clone())?;
981        }
982
983        Ok(())
984    }
985
986    #[test]
987    fn decode_tuple_four_refs_and_four_uint256() -> Result<()> {
988        let bytes = HashBytes([0xff; 32]);
989        let bytes_cell = CellBuilder::build_from(bytes)?;
990
991        let cell = {
992            let mut builder = CellBuilder::new();
993            builder.store_u32(0)?;
994            builder.store_reference(Cell::empty_cell())?;
995
996            builder.store_reference(bytes_cell.clone())?;
997            builder.store_reference(bytes_cell.clone())?;
998
999            let mut second_builder = CellBuilder::new();
1000            second_builder.store_reference(bytes_cell.clone())?;
1001            second_builder.store_u256(&bytes)?;
1002            second_builder.store_u256(&bytes)?;
1003            second_builder.store_u256(&bytes)?;
1004
1005            let mut third_builder = CellBuilder::new();
1006            third_builder.store_u256(&bytes)?;
1007
1008            second_builder.store_reference(third_builder.build()?)?;
1009            builder.store_reference(second_builder.build()?)?;
1010
1011            builder.build()?
1012        };
1013
1014        let value = AbiValue::unnamed_tuple([
1015            AbiValue::uint(32, 0_u32),
1016            AbiValue::Cell(Cell::empty_cell()),
1017            AbiValue::Cell(bytes_cell.clone()),
1018            AbiValue::Bytes(Bytes::copy_from_slice(bytes.as_slice())),
1019            AbiValue::Cell(bytes_cell),
1020            AbiValue::uint(256, BigUint::from_bytes_be(bytes.as_slice())),
1021            AbiValue::uint(256, BigUint::from_bytes_be(bytes.as_slice())),
1022            AbiValue::uint(256, BigUint::from_bytes_be(bytes.as_slice())),
1023            AbiValue::uint(256, BigUint::from_bytes_be(bytes.as_slice())),
1024        ]);
1025
1026        for v in VX_X {
1027            println!("ABIv{v}");
1028            load_simple(v, cell.clone(), value.clone())?;
1029        }
1030
1031        Ok(())
1032    }
1033
1034    #[test]
1035    fn decode_tuple_four_refs_and_one_uint256() -> Result<()> {
1036        let bytes = HashBytes([0x55; 32]);
1037        let bytes_cell = CellBuilder::build_from(bytes)?;
1038
1039        let mut builder = CellBuilder::new();
1040        builder.store_u32(0)?;
1041        builder.store_reference(Cell::empty_cell())?;
1042
1043        builder.store_reference(bytes_cell.clone())?;
1044        builder.store_reference(bytes_cell.clone())?;
1045
1046        let cell_v2 = {
1047            let mut builder = builder.clone();
1048            builder.store_reference(bytes_cell.clone())?;
1049            builder.store_u256(&bytes)?;
1050            builder.build()?
1051        };
1052
1053        let cell_v1 = {
1054            let mut child_builder = CellBuilder::new();
1055            child_builder.store_reference(bytes_cell.clone())?;
1056            child_builder.store_u256(&bytes)?;
1057
1058            builder.store_reference(child_builder.build()?)?;
1059            builder.build()?
1060        };
1061
1062        let value = AbiValue::unnamed_tuple([
1063            AbiValue::uint(32, 0_u32),
1064            AbiValue::Cell(Cell::empty_cell()),
1065            AbiValue::Cell(bytes_cell.clone()),
1066            AbiValue::Bytes(Bytes::copy_from_slice(bytes.as_slice())),
1067            AbiValue::Cell(bytes_cell.clone()),
1068            AbiValue::uint(256, BigUint::from_bytes_be(bytes.as_slice())),
1069        ]);
1070
1071        load_simple(AbiVersion::V1_0, cell_v1, value.clone())?;
1072        for v in V2_X {
1073            println!("ABIv{v}");
1074            load_simple(v, cell_v2.clone(), value.clone())?;
1075        }
1076
1077        Ok(())
1078    }
1079
1080    #[test]
1081    fn decode_map_simple() -> Result<()> {
1082        let bytes = HashBytes([0x55; 32]);
1083        let bytes_cell = CellBuilder::build_from(bytes)?;
1084
1085        let mut bytes_map = Dict::<u8, Cell>::new();
1086        for i in 1..=3 {
1087            bytes_map.set(i, bytes_cell.clone())?;
1088        }
1089        let bytes_map_value = AbiValue::map([
1090            (1u8, Bytes::copy_from_slice(bytes.as_slice())),
1091            (2, Bytes::copy_from_slice(bytes.as_slice())),
1092            (3, Bytes::copy_from_slice(bytes.as_slice())),
1093        ]);
1094
1095        let mut int_map = Dict::<i16, i128>::new();
1096        for i in -1..=1 {
1097            int_map.set(i, i as i128)?;
1098        }
1099        let int_map_value = AbiValue::map([(-1i16, -1i128), (0, 0), (1, 1)]);
1100
1101        let mut tuples_map = Dict::<u128, (u32, bool)>::new();
1102        for i in 1..=5 {
1103            tuples_map.set(i as u128, (i, i % 2 != 0))?;
1104        }
1105        let tuples_map_value = AbiValue::map([
1106            (1u128, (1u32, true)),
1107            (2, (2, false)),
1108            (3, (3, true)),
1109            (4, (4, false)),
1110            (5, (5, true)),
1111        ]);
1112
1113        //
1114        let context = Cell::empty_context();
1115        let mut builder = CellBuilder::new();
1116        builder.store_u32(0)?;
1117        builder.store_reference(Cell::empty_cell())?;
1118
1119        bytes_map.store_into(&mut builder, context)?;
1120        int_map.store_into(&mut builder, context)?;
1121
1122        let cell_v2 = {
1123            let mut builder = builder.clone();
1124            tuples_map.store_into(&mut builder, context)?;
1125            builder.store_bit_zero()?;
1126            builder.build()?
1127        };
1128
1129        let cell_v1 = {
1130            let mut child_builder = CellBuilder::new();
1131            tuples_map.store_into(&mut child_builder, context)?;
1132            child_builder.store_bit_zero()?;
1133
1134            builder.store_reference(child_builder.build()?)?;
1135            builder.build()?
1136        };
1137
1138        let value = AbiValue::unnamed_tuple([
1139            AbiValue::uint(32, 0u32),
1140            AbiValue::Cell(Cell::empty_cell()),
1141            bytes_map_value,
1142            int_map_value,
1143            tuples_map_value,
1144            AbiValue::map([] as [(HashBytes, bool); 0]),
1145        ]);
1146
1147        for v in VX_X {
1148            println!("ABIv{v}");
1149            load_simple(v, cell_v1.clone(), value.clone())?;
1150        }
1151
1152        for v in V2_X {
1153            println!("ABIv{v}");
1154            load_simple(v, cell_v2.clone(), value.clone())?;
1155        }
1156
1157        Ok(())
1158    }
1159
1160    #[test]
1161    fn decode_map_address() -> Result<()> {
1162        let addr1 = StdAddr::new(0, HashBytes([0x11; 32]));
1163        let addr2 = StdAddr::new(0, HashBytes([0x22; 32]));
1164
1165        let mut addr_map = Dict::<StdAddr, u32>::new();
1166        addr_map.set(&addr1, 123)?;
1167        addr_map.set(&addr2, 456)?;
1168
1169        let addr_map_value = AbiValue::map([(addr1, 123u32), (addr2, 456)]);
1170
1171        //
1172        let cell = {
1173            let mut builder = CellBuilder::new();
1174            builder.store_u32(0)?;
1175            builder.store_reference(Cell::empty_cell())?;
1176            addr_map.store_into(&mut builder, Cell::empty_context())?;
1177            builder.build()?
1178        };
1179
1180        let value = AbiValue::unnamed_tuple([
1181            AbiValue::uint(32, 0u32),
1182            AbiValue::Cell(Cell::empty_cell()),
1183            addr_map_value,
1184        ]);
1185
1186        for v in VX_X {
1187            println!("ABIv{v}");
1188            load_simple(v, cell.clone(), value.clone())?;
1189        }
1190
1191        Ok(())
1192    }
1193
1194    #[test]
1195    fn decode_map_big_value() -> Result<()> {
1196        let mut map_value = CellBuilder::new();
1197        map_value.store_u128(0)?;
1198        map_value.store_u128(1)?;
1199        map_value.store_u128(0)?;
1200        map_value.store_u128(2)?;
1201        map_value.store_u128(0)?;
1202        map_value.store_u128(3)?;
1203        map_value.store_reference(CellBuilder::build_from((0u128, 4u128))?)?;
1204        let map_value = map_value.build()?;
1205
1206        let mut key = CellBuilder::new();
1207        key.store_u128(0)?;
1208        key.store_u128(123)?;
1209
1210        let mut map = RawDict::<256>::new();
1211        map.set(key.as_data_slice(), &map_value)?;
1212
1213        //
1214        let mut key = CellBuilder::new();
1215        key.store_u32(0)?;
1216
1217        let mut array = RawDict::<32>::new();
1218        array.set(key.as_data_slice(), &map_value)?;
1219
1220        //
1221        let tuple_value = AbiValue::unnamed_tuple([
1222            AbiValue::uint(256, 1_u32),
1223            AbiValue::uint(256, 2_u32),
1224            AbiValue::uint(256, 3_u32),
1225            AbiValue::uint(256, 4_u32),
1226        ]);
1227
1228        let value = AbiValue::unnamed_tuple([
1229            AbiValue::uint(32, 0u32),
1230            AbiValue::Cell(Cell::empty_cell()),
1231            AbiValue::Map(
1232                PlainAbiType::Uint(256),
1233                Arc::new(tuple_value.get_type()),
1234                BTreeMap::from([(
1235                    PlainAbiValue::Uint(256, BigUint::from(123u32)),
1236                    tuple_value.clone(),
1237                )]),
1238            ),
1239            AbiValue::Array(Arc::new(tuple_value.get_type()), vec![tuple_value]),
1240        ]);
1241
1242        //
1243        let cell = {
1244            let context = Cell::empty_context();
1245            let mut builder = CellBuilder::new();
1246            builder.store_u32(0)?;
1247            builder.store_reference(Cell::empty_cell())?;
1248
1249            map.store_into(&mut builder, context)?;
1250
1251            builder.store_u32(1)?;
1252            array.store_into(&mut builder, context)?;
1253
1254            builder.build()?
1255        };
1256
1257        for v in V2_X {
1258            println!("ABIv{v}");
1259            load_simple(v, cell.clone(), value.clone())?;
1260        }
1261
1262        Ok(())
1263    }
1264
1265    #[test]
1266    fn decode_optional() -> Result<()> {
1267        const STR: &str = "Some string";
1268
1269        let string_cell = {
1270            let mut builder = CellBuilder::new();
1271            builder.store_raw(STR.as_bytes(), (STR.len() * 8) as u16)?;
1272            builder.build()?
1273        };
1274        let string_value = AbiValue::String(STR.to_owned());
1275
1276        let tuple_value = AbiValue::unnamed_tuple([
1277            string_value.clone(),
1278            string_value.clone(),
1279            string_value.clone(),
1280            string_value.clone(),
1281        ]);
1282
1283        let value = AbiValue::unnamed_tuple([
1284            AbiValue::uint(32, 0u32),
1285            AbiValue::Cell(Cell::empty_cell()),
1286            AbiValue::varint(16, -123),
1287            AbiValue::varuint(32, 456u32),
1288            AbiValue::optional(None::<bool>),
1289            AbiValue::Optional(
1290                Arc::new(AbiType::Uint(1022)),
1291                Some(Box::new(AbiValue::uint(1022, 1u32))),
1292            ),
1293            AbiValue::Optional(
1294                Arc::new(AbiType::varuint(128)),
1295                Some(Box::new(AbiValue::varuint(128, 123u32))),
1296            ),
1297            AbiValue::Optional(
1298                Arc::new(tuple_value.get_type()),
1299                Some(Box::new(tuple_value)),
1300            ),
1301        ]);
1302
1303        let cell = {
1304            let mut builder = CellBuilder::new();
1305            builder.store_u32(0)?;
1306            builder.store_reference(Cell::empty_cell())?;
1307
1308            builder.store_small_uint(1, 4)?;
1309            builder.store_u8(-123i8 as _)?;
1310
1311            builder.store_small_uint(2, 5)?;
1312            builder.store_u16(456)?;
1313
1314            builder.store_bit_zero()?;
1315
1316            builder.store_reference({
1317                let mut builder = CellBuilder::new();
1318                builder.store_bit_one()?;
1319                builder.store_zeros(127 * 8)?;
1320                builder.store_small_uint(1, 6)?;
1321
1322                builder.store_reference({
1323                    let mut builder = CellBuilder::new();
1324                    builder.store_bit_one()?;
1325                    builder.store_reference({
1326                        let mut builder = CellBuilder::new();
1327                        builder.store_small_uint(1, 7)?;
1328                        builder.store_u8(123)?;
1329                        builder.build()?
1330                    })?;
1331
1332                    builder.store_bit_one()?;
1333                    builder.store_reference(CellBuilder::build_from((
1334                        string_cell.clone(),
1335                        string_cell.clone(),
1336                        string_cell.clone(),
1337                        string_cell.clone(),
1338                    ))?)?;
1339
1340                    builder.build()?
1341                })?;
1342
1343                builder.build()?
1344            })?;
1345
1346            builder.build()?
1347        };
1348
1349        for v in V2_X {
1350            println!("ABIv{v}");
1351            load_simple(v, cell.clone(), value.clone())?;
1352        }
1353
1354        Ok(())
1355    }
1356
1357    #[test]
1358    fn decode_ref() -> Result<()> {
1359        let cell = {
1360            let mut builder = CellBuilder::new();
1361            builder.store_u32(0)?;
1362            builder.store_reference(Cell::empty_cell())?;
1363
1364            builder.store_reference(CellBuilder::build_from(123u64)?)?;
1365            builder.store_reference(CellBuilder::build_from((true, Cell::empty_cell()))?)?;
1366
1367            builder.build()?
1368        };
1369
1370        let value = AbiValue::unnamed_tuple([
1371            AbiValue::uint(32, 0u32),
1372            AbiValue::Cell(Cell::empty_cell()),
1373            AbiValue::reference(123u64),
1374            AbiValue::reference((true, Cell::empty_cell())),
1375        ]);
1376
1377        for v in V2_X {
1378            println!("ABIv{v}");
1379            load_simple(v, cell.clone(), value.clone())?;
1380        }
1381
1382        Ok(())
1383    }
1384}