soroban_sdk/testutils/
arbitrary.rs

1//! Support for fuzzing Soroban contracts with [`cargo-fuzz`].
2//!
3//! This module provides a pattern for generating Soroban contract types for the
4//! purpose of fuzzing Soroban contracts. It is focused on implementing the
5//! [`Arbitrary`] trait that `cargo-fuzz` relies on to feed fuzzers with
6//! generated Rust values.
7//!
8//! [`cargo-fuzz`]: https://github.com/rust-fuzz/cargo-fuzz/
9//! [`Arbitrary`]: ::arbitrary::Arbitrary
10//!
11//! This module
12//!
13//! - defines the [`SorobanArbitrary`] trait,
14//! - reexports the [`arbitrary`] crate and the [`Arbitrary`] type.
15//!
16//! This module is only available when the "testutils" Cargo feature is defined.
17//!
18//!
19//! ## About `cargo-fuzz` and `Arbitrary`
20//!
21//! In its basic operation `cargo-fuzz` fuzz generates raw bytes and feeds them
22//! to a program-dependent fuzzer designed to exercise a program, in our case a
23//! Soroban contract.
24//!
25//! `cargo-fuzz` programs declare their entry points with a macro:
26//!
27//! ```
28//! # macro_rules! fuzz_target {
29//! #     (|$data:ident: $dty: ty| $body:block) => { };
30//! # }
31//! fuzz_target!(|input: &[u8]| {
32//!     // feed bytes to the program
33//! });
34//! ```
35//!
36//! More sophisticated fuzzers accept not bytes but Rust types:
37//!
38//! ```
39//! # use arbitrary::Arbitrary;
40//! # macro_rules! fuzz_target {
41//! #     (|$data:ident: $dty: ty| $body:block) => { };
42//! # }
43//! #[derive(Arbitrary, Debug)]
44//! struct FuzzDeposit {
45//!     deposit_amount: i128,
46//! }
47//!
48//! fuzz_target!(|input: FuzzDeposit| {
49//!     // fuzz the program based on the input
50//! });
51//! ```
52//!
53//! Types accepted as input to `fuzz_target` must implement the `Arbitrary` trait,
54//! which transforms bytes to Rust types.
55//!
56//!
57//! ## The `SorobanArbitrary` trait
58//!
59//! Soroban types are managed by the host environment, and so must be created
60//! from an [`Env`] value; `Arbitrary` values though must be created from
61//! nothing but bytes. The [`SorobanArbitrary`] trait, implemented for all
62//! Soroban contract types, exists to bridge this gap: it defines a _prototype_
63//! pattern whereby the `fuzz_target` macro creates prototype values that the
64//! fuzz program can convert to contract values with the standard soroban
65//! conversion traits, [`FromVal`] or [`IntoVal`].
66//!
67//! [`Env`]: crate::Env
68//! [`FromVal`]: crate::FromVal
69//! [`IntoVal`]: crate::IntoVal
70//!
71//! The types of prototypes are identified by the associated type,
72//! [`SorobanArbitrary::Prototype`]:
73//!
74//! ```
75//! # use soroban_sdk::testutils::arbitrary::Arbitrary;
76//! # use soroban_sdk::{TryFromVal, IntoVal, Val, Env};
77//! pub trait SorobanArbitrary:
78//!     TryFromVal<Env, Self::Prototype> + IntoVal<Env, Val> + TryFromVal<Env, Val>
79//! {
80//!     type Prototype: for <'a> Arbitrary<'a>;
81//! }
82//! ```
83//!
84//! Types that implement `SorobanArbitrary` include:
85//!
86//! - `i32`, `u32`, `i64`, `u64`, `i128`, `u128`, `I256`, `U256`, `()`, and `bool`,
87//! - [`Error`],
88//! - [`Bytes`], [`BytesN`], [`Vec`], [`Map`],
89//! - [`Address`], [`Symbol`],
90//! - [`Val`],
91//!
92//! [`I256`]: crate::I256
93//! [`U256`]: crate::U256
94//! [`Error`]: crate::Error
95//! [`Bytes`]: crate::Bytes
96//! [`BytesN`]: crate::BytesN
97//! [`Vec`]: crate::Vec
98//! [`Map`]: crate::Map
99//! [`Address`]: crate::Address
100//! [`Symbol`]: crate::Symbol
101//! [`Val`]: crate::Val
102//!
103//! All user-defined contract types, those with the [`contracttype`] attribute,
104//! automatically derive `SorobanArbitrary`. Note that `SorobanArbitrary` is
105//! only derived when the "testutils" Cargo feature is active. This implies
106//! that, in general, to make a Soroban contract fuzzable, the contract crate
107//! must define a "testutils" Cargo feature, that feature should turn on the
108//! "soroban-sdk/testutils" feature, and the fuzz test, which is its own crate,
109//! must turn that feature on.
110//!
111//! [`contracttype`]: crate::contracttype
112//!
113//!
114//! ## Example: take a Soroban `Vec` of `Address` as fuzzer input
115//!
116//! ```
117//! # macro_rules! fuzz_target {
118//! #     (|$data:ident: $dty: ty| $body:block) => { };
119//! # }
120//! use soroban_sdk::{Address, Env, Vec};
121//! use soroban_sdk::testutils::arbitrary::SorobanArbitrary;
122//!
123//! fuzz_target!(|input: <Vec<Address> as SorobanArbitrary>::Prototype| {
124//!     let env = Env::default();
125//!     let addresses: Vec<Address> = input.into_val(&env);
126//!     // fuzz the program based on the input
127//! });
128//! ```
129//!
130//!
131//! ## Example: take a custom contract type as fuzzer input
132//!
133//! ```
134//! # macro_rules! fuzz_target {
135//! #     (|$data:ident: $dty: ty| $body:block) => { };
136//! # }
137//! use soroban_sdk::{Address, Env, Vec};
138//! use soroban_sdk::contracttype;
139//! use soroban_sdk::testutils::arbitrary::{Arbitrary, SorobanArbitrary};
140//! use std::vec::Vec as RustVec;
141//!
142//! #[derive(Arbitrary, Debug)]
143//! struct TestInput {
144//!     deposit_amount: i128,
145//!     claim_address: <Address as SorobanArbitrary>::Prototype,
146//!     time_bound: <TimeBound as SorobanArbitrary>::Prototype,
147//! }
148//!
149//! #[contracttype]
150//! pub struct TimeBound {
151//!     pub kind: TimeBoundKind,
152//!     pub timestamp: u64,
153//! }
154//!
155//! #[contracttype]
156//! pub enum TimeBoundKind {
157//!     Before,
158//!     After,
159//! }
160//!
161//! fuzz_target!(|input: TestInput| {
162//!     let env = Env::default();
163//!     let claim_address: Address = input.claim_address.into_val(&env);
164//!     let time_bound: TimeBound = input.time_bound.into_val(&env);
165//!     // fuzz the program based on the input
166//! });
167//! ```
168
169/// A reexport of the `arbitrary` crate.
170///
171/// Used by the `contracttype` macro to derive `Arbitrary`.
172pub use arbitrary;
173
174// Used often enough in fuzz tests to want direct access to it.
175pub use arbitrary::Arbitrary;
176
177// Used by `contracttype`
178#[doc(hidden)]
179pub use std;
180
181pub use api::*;
182pub use fuzz_test_helpers::*;
183
184/// The traits that must be implemented on Soroban types to support fuzzing.
185///
186/// These allow for ergonomic conversion from a randomly-generated "prototype"
187/// that implements `Arbitrary` into `Env`-"hosted" values that are paired with an
188/// `Env`.
189///
190/// These traits are intended to be easy to automatically derive.
191mod api {
192    use crate::Env;
193    use crate::Val;
194    use crate::{IntoVal, TryFromVal};
195    use arbitrary::Arbitrary;
196
197    /// An `Env`-hosted contract value that can be randomly generated.
198    ///
199    /// Types that implement `SorabanArbitrary` have an associated "prototype"
200    /// type that implements [`Arbitrary`].
201    ///
202    /// This exists partly so that the prototype can be named like
203    ///
204    /// ```
205    /// # macro_rules! fuzz_target {
206    /// #     (|$data:ident: $dty: ty| $body:block) => { };
207    /// # }
208    /// # use soroban_sdk::{Address, Env, Vec, Bytes};
209    /// # use soroban_sdk::testutils::arbitrary::SorobanArbitrary;
210    /// fuzz_target!(|input: <Bytes as SorobanArbitrary>::Prototype| {
211    ///     // ...
212    /// });
213    /// ```
214    // This also makes derivation of `SorobanArbitrary` for custom types easier
215    // since we depend on all fields also implementing `SorobanArbitrary`.
216    //
217    // The IntoVal<Env, Val> + TryFromVal<Env, Val> bounds are to satisfy
218    // the bounds of Vec and Map, so that collections of prototypes can be
219    // converted to contract types.
220    pub trait SorobanArbitrary:
221        TryFromVal<Env, Self::Prototype> + IntoVal<Env, Val> + TryFromVal<Env, Val>
222    {
223        /// A type that implements [`Arbitrary`] and can be converted to this
224        /// [`SorobanArbitrary`] type.
225        // NB: The `Arbitrary` bound here is not necessary for the correct use of
226        // `SorobanArbitrary`, but it makes the purpose clear.
227        type Prototype: for<'a> Arbitrary<'a>;
228    }
229}
230
231/// Implementations of `soroban_sdk::testutils::arbitrary::api` for Rust scalar types.
232///
233/// These types
234///
235/// - do not have a distinct `Arbitrary` prototype,
236///   i.e. they use themselves as the `SorobanArbitrary::Prototype` type,
237/// - implement `Arbitrary` in the `arbitrary` crate,
238/// - trivially implement `TryFromVal<Env, SorobanArbitrary::Prototype>`,
239///
240/// Examples:
241///
242/// - `u32`
243mod scalars {
244    use super::api::*;
245
246    impl SorobanArbitrary for () {
247        type Prototype = ();
248    }
249
250    impl SorobanArbitrary for bool {
251        type Prototype = bool;
252    }
253
254    impl SorobanArbitrary for u32 {
255        type Prototype = u32;
256    }
257
258    impl SorobanArbitrary for i32 {
259        type Prototype = i32;
260    }
261
262    impl SorobanArbitrary for u64 {
263        type Prototype = u64;
264    }
265
266    impl SorobanArbitrary for i64 {
267        type Prototype = i64;
268    }
269
270    impl SorobanArbitrary for u128 {
271        type Prototype = u128;
272    }
273
274    impl SorobanArbitrary for i128 {
275        type Prototype = i128;
276    }
277}
278
279/// Implementations of `soroban_sdk::testutils::arbitrary::api` for Soroban types that do not
280/// need access to the Soroban host environment.
281///
282/// These types
283///
284/// - do not have a distinct `Arbitrary` prototype,
285///   i.e. they use themselves as the `SorobanArbitrary::Prototype` type,
286/// - implement `Arbitrary` in the `soroban-env-common` crate,
287/// - trivially implement `TryFromVal<Env, SorobanArbitrary::Prototype>`,
288///
289/// Examples:
290///
291/// - `Error`
292mod simple {
293    use super::api::*;
294    pub use crate::Error;
295
296    impl SorobanArbitrary for Error {
297        type Prototype = Error;
298    }
299}
300
301/// Implementations of `soroban_sdk::testutils::arbitrary::api` for Soroban types that do
302/// need access to the Soroban host environment.
303///
304/// These types
305///
306/// - have a distinct `Arbitrary` prototype that derives `Arbitrary`,
307/// - require an `Env` to be converted to their actual contract type.
308///
309/// Examples:
310///
311/// - `Vec`
312mod objects {
313    use arbitrary::{Arbitrary, Result as ArbitraryResult, Unstructured};
314
315    use super::api::*;
316    use super::composite::ArbitraryVal;
317    use crate::env::FromVal;
318    use crate::ConversionError;
319    use crate::{Env, IntoVal, TryFromVal, TryIntoVal};
320
321    use crate::xdr::{Int256Parts, ScVal, UInt256Parts};
322    use crate::{
323        crypto::bls12_381::{
324            Fp, Fp2, Fr, G1Affine, G2Affine, FP2_SERIALIZED_SIZE, FP_SERIALIZED_SIZE,
325            G1_SERIALIZED_SIZE, G2_SERIALIZED_SIZE,
326        },
327        Address, Bytes, BytesN, Duration, Map, String, Symbol, Timepoint, Val, Vec, I256, U256,
328    };
329
330    use std::string::String as RustString;
331    use std::vec::Vec as RustVec;
332
333    //////////////////////////////////
334
335    #[derive(Arbitrary, Debug, Clone, Eq, PartialEq, Ord, PartialOrd)]
336    pub struct ArbitraryOption<T>(Option<T>);
337
338    impl<T> SorobanArbitrary for Option<T>
339    where
340        T: SorobanArbitrary,
341        Val: TryFromVal<Env, T>,
342    {
343        type Prototype = ArbitraryOption<T::Prototype>;
344    }
345
346    impl<T> TryFromVal<Env, ArbitraryOption<T::Prototype>> for Option<T>
347    where
348        T: SorobanArbitrary,
349    {
350        type Error = ConversionError;
351        fn try_from_val(env: &Env, v: &ArbitraryOption<T::Prototype>) -> Result<Self, Self::Error> {
352            match v.0 {
353                Some(ref t) => Ok(Some(t.into_val(env))),
354                None => Ok(None),
355            }
356        }
357    }
358
359    //////////////////////////////////
360
361    #[derive(Arbitrary, Debug, Clone, Eq, PartialEq, Ord, PartialOrd)]
362    pub struct ArbitraryU256 {
363        parts: (u64, u64, u64, u64),
364    }
365
366    impl SorobanArbitrary for U256 {
367        type Prototype = ArbitraryU256;
368    }
369
370    impl TryFromVal<Env, ArbitraryU256> for U256 {
371        type Error = ConversionError;
372        fn try_from_val(env: &Env, v: &ArbitraryU256) -> Result<Self, Self::Error> {
373            let v = ScVal::U256(UInt256Parts {
374                hi_hi: v.parts.0,
375                hi_lo: v.parts.1,
376                lo_hi: v.parts.2,
377                lo_lo: v.parts.3,
378            });
379            let v = Val::try_from_val(env, &v)?;
380            v.try_into_val(env)
381        }
382    }
383
384    //////////////////////////////////
385
386    #[derive(Arbitrary, Debug, Clone, Eq, PartialEq, Ord, PartialOrd)]
387    pub struct ArbitraryI256 {
388        parts: (i64, u64, u64, u64),
389    }
390
391    impl SorobanArbitrary for I256 {
392        type Prototype = ArbitraryI256;
393    }
394
395    impl TryFromVal<Env, ArbitraryI256> for I256 {
396        type Error = ConversionError;
397        fn try_from_val(env: &Env, v: &ArbitraryI256) -> Result<Self, Self::Error> {
398            let v = ScVal::I256(Int256Parts {
399                hi_hi: v.parts.0,
400                hi_lo: v.parts.1,
401                lo_hi: v.parts.2,
402                lo_lo: v.parts.3,
403            });
404            let v = Val::try_from_val(env, &v)?;
405            v.try_into_val(env)
406        }
407    }
408
409    //////////////////////////////////
410
411    #[derive(Arbitrary, Debug, Clone, Eq, PartialEq, Ord, PartialOrd)]
412    pub struct ArbitraryBytes {
413        vec: RustVec<u8>,
414    }
415
416    impl SorobanArbitrary for Bytes {
417        type Prototype = ArbitraryBytes;
418    }
419
420    impl TryFromVal<Env, ArbitraryBytes> for Bytes {
421        type Error = ConversionError;
422        fn try_from_val(env: &Env, v: &ArbitraryBytes) -> Result<Self, Self::Error> {
423            Self::try_from_val(env, &v.vec.as_slice())
424        }
425    }
426
427    //////////////////////////////////
428
429    #[derive(Arbitrary, Debug, Clone, Eq, PartialEq, Ord, PartialOrd)]
430    pub struct ArbitraryString {
431        inner: RustString,
432    }
433
434    impl SorobanArbitrary for String {
435        type Prototype = ArbitraryString;
436    }
437
438    impl TryFromVal<Env, ArbitraryString> for String {
439        type Error = ConversionError;
440        fn try_from_val(env: &Env, v: &ArbitraryString) -> Result<Self, Self::Error> {
441            Self::try_from_val(env, &v.inner.as_str())
442        }
443    }
444
445    //////////////////////////////////
446
447    #[derive(Arbitrary, Debug, Clone, Eq, PartialEq, Ord, PartialOrd)]
448    pub struct ArbitraryBytesN<const N: usize> {
449        array: [u8; N],
450    }
451
452    impl<const N: usize> SorobanArbitrary for BytesN<N> {
453        type Prototype = ArbitraryBytesN<N>;
454    }
455
456    impl<const N: usize> TryFromVal<Env, ArbitraryBytesN<N>> for BytesN<N> {
457        type Error = ConversionError;
458        fn try_from_val(env: &Env, v: &ArbitraryBytesN<N>) -> Result<Self, Self::Error> {
459            Self::try_from_val(env, &v.array)
460        }
461    }
462
463    //////////////////////////////////
464
465    #[derive(Debug, Clone, Eq, PartialEq, Ord, PartialOrd)]
466    pub struct ArbitrarySymbol {
467        s: RustString,
468    }
469
470    impl<'a> Arbitrary<'a> for ArbitrarySymbol {
471        fn arbitrary(u: &mut Unstructured<'a>) -> ArbitraryResult<ArbitrarySymbol> {
472            let valid_chars = "_abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
473            let valid_chars = valid_chars.as_bytes();
474            let mut chars = vec![];
475            let len = u.int_in_range(0..=32)?;
476            for _ in 0..len {
477                let ch = u.choose(valid_chars)?;
478                chars.push(*ch);
479            }
480            Ok(ArbitrarySymbol {
481                s: RustString::from_utf8(chars).expect("utf8"),
482            })
483        }
484    }
485
486    impl SorobanArbitrary for Symbol {
487        type Prototype = ArbitrarySymbol;
488    }
489
490    impl TryFromVal<Env, ArbitrarySymbol> for Symbol {
491        type Error = ConversionError;
492        fn try_from_val(env: &Env, v: &ArbitrarySymbol) -> Result<Self, Self::Error> {
493            Self::try_from_val(env, &v.s.as_str())
494        }
495    }
496
497    //////////////////////////////////
498
499    #[derive(Debug, Clone, Eq, PartialEq, Ord, PartialOrd)]
500    pub enum ArbitraryVec<T> {
501        Good(RustVec<T>),
502        // Vec<T> can be constructed with non-T values.
503        Wrong(RustVec<ArbitraryVal>),
504    }
505
506    impl<'a, T> Arbitrary<'a> for ArbitraryVec<T>
507    where
508        T: Arbitrary<'a>,
509    {
510        fn arbitrary(u: &mut Unstructured<'a>) -> ArbitraryResult<ArbitraryVec<T>> {
511            // How frequently we provide ArbitraryVec::Wrong
512            const WRONG_TYPE_RATIO: (u16, u16) = (1, 1000);
513
514            if u.ratio(WRONG_TYPE_RATIO.0, WRONG_TYPE_RATIO.1)? {
515                Ok(ArbitraryVec::Wrong(Arbitrary::arbitrary(u)?))
516            } else {
517                Ok(ArbitraryVec::Good(Arbitrary::arbitrary(u)?))
518            }
519        }
520    }
521
522    impl<T> SorobanArbitrary for Vec<T>
523    where
524        T: SorobanArbitrary,
525    {
526        type Prototype = ArbitraryVec<T::Prototype>;
527    }
528
529    impl<T> TryFromVal<Env, ArbitraryVec<T::Prototype>> for Vec<T>
530    where
531        T: SorobanArbitrary,
532    {
533        type Error = ConversionError;
534        fn try_from_val(env: &Env, v: &ArbitraryVec<T::Prototype>) -> Result<Self, Self::Error> {
535            match v {
536                ArbitraryVec::Good(vec) => {
537                    let mut buf: Vec<T> = Vec::new(env);
538                    for item in vec.iter() {
539                        buf.push_back(item.into_val(env));
540                    }
541                    Ok(buf)
542                }
543                ArbitraryVec::Wrong(vec) => {
544                    let mut buf: Vec<Val> = Vec::new(env);
545                    for item in vec.iter() {
546                        buf.push_back(item.into_val(env));
547                    }
548                    Ok(Vec::<T>::from_val(env, &buf.to_val()))
549                }
550            }
551        }
552    }
553
554    //////////////////////////////////
555
556    #[derive(Debug, Clone, Eq, PartialEq, Ord, PartialOrd)]
557    pub enum ArbitraryMap<K, V> {
558        Good(RustVec<(K, V)>),
559        // Maps can be constructed with non-T K/Vs
560        WrongKey(RustVec<(ArbitraryVal, V)>),
561        WrongValue(RustVec<(K, ArbitraryVal)>),
562    }
563
564    impl<'a, K, V> Arbitrary<'a> for ArbitraryMap<K, V>
565    where
566        K: Arbitrary<'a>,
567        V: Arbitrary<'a>,
568    {
569        fn arbitrary(u: &mut Unstructured<'a>) -> ArbitraryResult<ArbitraryMap<K, V>> {
570            // How frequently we provide ArbitraryMap::Wrong*
571            const WRONG_TYPE_RATIO: (u16, u16) = (1, 1000);
572
573            if u.ratio(WRONG_TYPE_RATIO.0, WRONG_TYPE_RATIO.1)? {
574                if u.arbitrary::<bool>()? {
575                    Ok(ArbitraryMap::WrongKey(Arbitrary::arbitrary(u)?))
576                } else {
577                    Ok(ArbitraryMap::WrongValue(Arbitrary::arbitrary(u)?))
578                }
579            } else {
580                Ok(ArbitraryMap::Good(Arbitrary::arbitrary(u)?))
581            }
582        }
583    }
584
585    impl<K, V> SorobanArbitrary for Map<K, V>
586    where
587        K: SorobanArbitrary,
588        V: SorobanArbitrary,
589    {
590        type Prototype = ArbitraryMap<K::Prototype, V::Prototype>;
591    }
592
593    impl<K, V> TryFromVal<Env, ArbitraryMap<K::Prototype, V::Prototype>> for Map<K, V>
594    where
595        K: SorobanArbitrary,
596        V: SorobanArbitrary,
597    {
598        type Error = ConversionError;
599        fn try_from_val(
600            env: &Env,
601            v: &ArbitraryMap<K::Prototype, V::Prototype>,
602        ) -> Result<Self, Self::Error> {
603            match v {
604                ArbitraryMap::Good(vec) => {
605                    let mut map: Map<K, V> = Map::new(env);
606                    for (k, v) in vec.iter() {
607                        map.set(k.into_val(env), v.into_val(env));
608                    }
609                    Ok(map)
610                }
611                ArbitraryMap::WrongKey(vec) => {
612                    let mut map: Map<Val, V> = Map::new(env);
613                    for (k, v) in vec.iter() {
614                        map.set(k.into_val(env), v.into_val(env));
615                    }
616                    Ok(Map::<K, V>::from_val(env, &map.to_val()))
617                }
618                ArbitraryMap::WrongValue(vec) => {
619                    let mut map: Map<K, Val> = Map::new(env);
620                    for (k, v) in vec.iter() {
621                        map.set(k.into_val(env), v.into_val(env));
622                    }
623                    Ok(Map::<K, V>::from_val(env, &map.to_val()))
624                }
625            }
626        }
627    }
628
629    //////////////////////////////////
630
631    #[derive(Arbitrary, Debug, Clone, Eq, PartialEq, Ord, PartialOrd)]
632    pub struct ArbitraryAddress {
633        inner: [u8; 32],
634    }
635
636    impl SorobanArbitrary for Address {
637        type Prototype = ArbitraryAddress;
638    }
639
640    impl TryFromVal<Env, ArbitraryAddress> for Address {
641        type Error = ConversionError;
642        fn try_from_val(env: &Env, v: &ArbitraryAddress) -> Result<Self, Self::Error> {
643            use crate::env::xdr::{Hash, ScAddress};
644
645            let sc_addr = ScVal::Address(ScAddress::Contract(Hash(v.inner)));
646            Ok(sc_addr.into_val(env))
647        }
648    }
649
650    //////////////////////////////////
651
652    #[derive(Arbitrary, Debug, Clone, Eq, PartialEq, Ord, PartialOrd)]
653    pub struct ArbitraryTimepoint {
654        inner: u64,
655    }
656
657    impl SorobanArbitrary for Timepoint {
658        type Prototype = ArbitraryTimepoint;
659    }
660
661    impl TryFromVal<Env, ArbitraryTimepoint> for Timepoint {
662        type Error = ConversionError;
663        fn try_from_val(env: &Env, v: &ArbitraryTimepoint) -> Result<Self, Self::Error> {
664            let sc_timepoint = ScVal::Timepoint(crate::xdr::TimePoint::from(v.inner));
665            Ok(sc_timepoint.into_val(env))
666        }
667    }
668
669    //////////////////////////////////
670
671    #[derive(Arbitrary, Debug, Clone, Eq, PartialEq, Ord, PartialOrd)]
672    pub struct ArbitraryDuration {
673        inner: u64,
674    }
675
676    impl SorobanArbitrary for Duration {
677        type Prototype = ArbitraryDuration;
678    }
679
680    impl TryFromVal<Env, ArbitraryDuration> for Duration {
681        type Error = ConversionError;
682        fn try_from_val(env: &Env, v: &ArbitraryDuration) -> Result<Self, Self::Error> {
683            let sc_duration = ScVal::Duration(crate::xdr::Duration::from(v.inner));
684            Ok(sc_duration.into_val(env))
685        }
686    }
687
688    // For Fp (48 bytes)
689    #[derive(Arbitrary, Debug, Clone, Eq, PartialEq, Ord, PartialOrd)]
690    pub struct ArbitraryFp {
691        bytes: [u8; FP_SERIALIZED_SIZE],
692    }
693
694    impl SorobanArbitrary for Fp {
695        type Prototype = ArbitraryFp;
696    }
697
698    impl TryFromVal<Env, ArbitraryFp> for Fp {
699        type Error = ConversionError;
700
701        fn try_from_val(env: &Env, v: &ArbitraryFp) -> Result<Self, Self::Error> {
702            Ok(Fp::from_array(env, &v.bytes))
703        }
704    }
705
706    // For Fp2 (96 bytes)
707    #[derive(Arbitrary, Debug, Clone, Eq, PartialEq, Ord, PartialOrd)]
708    pub struct ArbitraryFp2 {
709        bytes: [u8; FP2_SERIALIZED_SIZE],
710    }
711
712    impl SorobanArbitrary for Fp2 {
713        type Prototype = ArbitraryFp2;
714    }
715
716    impl TryFromVal<Env, ArbitraryFp2> for Fp2 {
717        type Error = ConversionError;
718
719        fn try_from_val(env: &Env, v: &ArbitraryFp2) -> Result<Self, Self::Error> {
720            Ok(Fp2::from_array(env, &v.bytes))
721        }
722    }
723
724    // For G1Affine (96 bytes)
725    #[derive(Arbitrary, Debug, Clone, Eq, PartialEq, Ord, PartialOrd)]
726    pub struct ArbitraryG1Affine {
727        bytes: [u8; G1_SERIALIZED_SIZE],
728    }
729
730    impl SorobanArbitrary for G1Affine {
731        type Prototype = ArbitraryG1Affine;
732    }
733
734    impl TryFromVal<Env, ArbitraryG1Affine> for G1Affine {
735        type Error = ConversionError;
736
737        fn try_from_val(env: &Env, v: &ArbitraryG1Affine) -> Result<Self, Self::Error> {
738            let mut bytes = v.bytes;
739            // the top 3 bits in a G1 point are reserved for flags:
740            // compression_flag (bit 0), infinity_flag (bit 1) and sort_flag
741            // (bit 2). Only infinity_flag is possible to be set, in which case
742            // the rest of the bytes must be zeros. The host will reject any
743            // invalid input. Manually taking care of the flag bits here to give
744            // it better chance of being a valid input.
745            const INFINITY_FLAG: u8 = 0b0100_0000;
746            const FLAG_MASK: u8 = 0b1110_0000;
747            if (bytes[0] & INFINITY_FLAG) != 0 {
748                // infinity flag set, clear rest of bits
749                bytes = [0; 96];
750                bytes[0] = INFINITY_FLAG;
751            } else {
752                // not an infinity point, we clear the flag bits
753                bytes[0] &= !FLAG_MASK
754            }
755            Ok(G1Affine::from_array(env, &bytes))
756        }
757    }
758
759    // For G2Affine (192 bytes)
760    #[derive(Arbitrary, Debug, Clone, Eq, PartialEq, Ord, PartialOrd)]
761    pub struct ArbitraryG2Affine {
762        bytes: [u8; G2_SERIALIZED_SIZE],
763    }
764
765    impl SorobanArbitrary for G2Affine {
766        type Prototype = ArbitraryG2Affine;
767    }
768
769    impl TryFromVal<Env, ArbitraryG2Affine> for G2Affine {
770        type Error = ConversionError;
771
772        fn try_from_val(env: &Env, v: &ArbitraryG2Affine) -> Result<Self, Self::Error> {
773            let mut bytes = v.bytes;
774            // the top 3 bits in a G1 point are reserved for flags:
775            // compression_flag (bit 0), infinity_flag (bit 1) and sort_flag
776            // (bit 2). Only infinity_flag is possible to be set, in which case
777            // the rest of the bytes must be zeros. The host will reject any
778            // invalid input. Manually taking care of the flag bits here to give
779            // it better chance of being a valid input.
780            const INFINITY_FLAG: u8 = 0b0100_0000;
781            const FLAG_MASK: u8 = 0b1110_0000;
782            if (bytes[0] & INFINITY_FLAG) != 0 {
783                // infinity flag set, clear rest of bits
784                bytes = [0; 192];
785                bytes[0] = INFINITY_FLAG;
786            } else {
787                // not an infinity point, we clear the flag bits
788                bytes[0] &= !FLAG_MASK
789            }
790            Ok(G2Affine::from_array(env, &bytes))
791        }
792    }
793
794    #[derive(Arbitrary, Debug, Clone, Eq, PartialEq, Ord, PartialOrd)]
795    pub struct ArbitraryFr {
796        bytes: [u8; 32],
797    }
798
799    impl SorobanArbitrary for Fr {
800        type Prototype = ArbitraryFr;
801    }
802
803    impl TryFromVal<Env, ArbitraryFr> for Fr {
804        type Error = ConversionError;
805
806        fn try_from_val(env: &Env, v: &ArbitraryFr) -> Result<Self, Self::Error> {
807            // Convert bytes to Fr via U256
808            Ok(Fr::from_bytes(BytesN::from_array(env, &v.bytes)))
809        }
810    }
811}
812
813/// Implementations of `soroban_sdk::testutils::arbitrary::api` for tuples of Soroban types.
814///
815/// The implementation is similar to objects, but macroized.
816mod tuples {
817    use super::api::*;
818    use crate::ConversionError;
819    use crate::{Env, IntoVal, TryFromVal, TryIntoVal, Val};
820    use arbitrary::Arbitrary;
821
822    macro_rules! impl_tuple {
823        ($name: ident, $($ty: ident),+ ) => {
824            #[allow(non_snake_case)] // naming fields T1, etc.
825            #[derive(Arbitrary, Debug, Clone, Eq, PartialEq, Ord, PartialOrd)]
826            pub struct $name<$($ty,)*> {
827                $($ty: $ty,)*
828            }
829
830            impl<$($ty,)*> SorobanArbitrary for ($($ty,)*)
831            where $($ty: SorobanArbitrary + TryIntoVal<Env, Val>,)*
832            {
833                type Prototype = $name<$($ty::Prototype,)*>;
834            }
835
836            impl<$($ty,)*> TryFromVal<Env, $name<$($ty::Prototype,)*>> for ($($ty,)*)
837            where $($ty: SorobanArbitrary,)*
838            {
839                type Error = ConversionError;
840                fn try_from_val(env: &Env, v: &$name<$($ty::Prototype,)*>) -> Result<Self, Self::Error> {
841                    Ok(($(
842                        v.$ty.into_val(env),
843                    )*))
844                }
845            }
846        }
847    }
848
849    impl_tuple!(ArbitraryTuple1, T1);
850    impl_tuple!(ArbitraryTuple2, T1, T2);
851    impl_tuple!(ArbitraryTuple3, T1, T2, T3);
852    impl_tuple!(ArbitraryTuple4, T1, T2, T3, T4);
853    impl_tuple!(ArbitraryTuple5, T1, T2, T3, T4, T5);
854    impl_tuple!(ArbitraryTuple6, T1, T2, T3, T4, T5, T6);
855    impl_tuple!(ArbitraryTuple7, T1, T2, T3, T4, T5, T6, T7);
856    impl_tuple!(ArbitraryTuple8, T1, T2, T3, T4, T5, T6, T7, T8);
857    impl_tuple!(ArbitraryTuple9, T1, T2, T3, T4, T5, T6, T7, T8, T9);
858    impl_tuple!(ArbitraryTuple10, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10);
859    impl_tuple!(
860        ArbitraryTuple11,
861        T1,
862        T2,
863        T3,
864        T4,
865        T5,
866        T6,
867        T7,
868        T8,
869        T9,
870        T10,
871        T11
872    );
873    impl_tuple!(
874        ArbitraryTuple12,
875        T1,
876        T2,
877        T3,
878        T4,
879        T5,
880        T6,
881        T7,
882        T8,
883        T9,
884        T10,
885        T11,
886        T12
887    );
888}
889
890/// Implementations of `soroban_sdk::testutils::arbitrary::api` for `Val`.
891mod composite {
892    use arbitrary::Arbitrary;
893
894    use super::api::*;
895    use crate::ConversionError;
896    use crate::{Env, IntoVal, TryFromVal};
897
898    use super::objects::*;
899    use super::simple::*;
900    use crate::{
901        Address, Bytes, BytesN, Duration, Map, String, Symbol, Timepoint, Val, Vec, I256, U256,
902    };
903
904    #[derive(Arbitrary, Debug, Clone, Eq, PartialEq, Ord, PartialOrd)]
905    pub enum ArbitraryVal {
906        Void,
907        Bool(bool),
908        Error(Error),
909        U32(u32),
910        I32(i32),
911        U64(u64),
912        I64(i64),
913        U128(u128),
914        I128(i128),
915        U256(ArbitraryU256),
916        I256(ArbitraryI256),
917        Bytes(ArbitraryBytes),
918        String(ArbitraryString),
919        Symbol(ArbitrarySymbol),
920        Vec(ArbitraryValVec),
921        Map(ArbitraryValMap),
922        Address(ArbitraryAddress),
923        Timepoint(ArbitraryTimepoint),
924        Duration(ArbitraryDuration),
925        Option(ArbitraryValOption),
926    }
927
928    impl SorobanArbitrary for Val {
929        type Prototype = ArbitraryVal;
930    }
931
932    impl TryFromVal<Env, ArbitraryVal> for Val {
933        type Error = ConversionError;
934        fn try_from_val(env: &Env, v: &ArbitraryVal) -> Result<Self, Self::Error> {
935            Ok(match v {
936                ArbitraryVal::Void => Val::VOID.into(),
937                ArbitraryVal::Bool(v) => v.into_val(env),
938                ArbitraryVal::Error(v) => v.into_val(env),
939                ArbitraryVal::U32(v) => v.into_val(env),
940                ArbitraryVal::I32(v) => v.into_val(env),
941                ArbitraryVal::U64(v) => v.into_val(env),
942                ArbitraryVal::I64(v) => v.into_val(env),
943                ArbitraryVal::U256(v) => {
944                    let v: U256 = v.into_val(env);
945                    v.into_val(env)
946                }
947                ArbitraryVal::I256(v) => {
948                    let v: I256 = v.into_val(env);
949                    v.into_val(env)
950                }
951                ArbitraryVal::U128(v) => v.into_val(env),
952                ArbitraryVal::I128(v) => v.into_val(env),
953                ArbitraryVal::Bytes(v) => {
954                    let v: Bytes = v.into_val(env);
955                    v.into_val(env)
956                }
957                ArbitraryVal::String(v) => {
958                    let v: String = v.into_val(env);
959                    v.into_val(env)
960                }
961                ArbitraryVal::Symbol(v) => {
962                    let v: Symbol = v.into_val(env);
963                    v.into_val(env)
964                }
965                ArbitraryVal::Vec(v) => v.into_val(env),
966                ArbitraryVal::Map(v) => v.into_val(env),
967                ArbitraryVal::Address(v) => {
968                    let v: Address = v.into_val(env);
969                    v.into_val(env)
970                }
971                ArbitraryVal::Timepoint(v) => {
972                    let v: Timepoint = v.into_val(env);
973                    v.into_val(env)
974                }
975                ArbitraryVal::Duration(v) => {
976                    let v: Duration = v.into_val(env);
977                    v.into_val(env)
978                }
979                ArbitraryVal::Option(v) => v.into_val(env),
980            })
981        }
982    }
983
984    #[derive(Arbitrary, Debug, Clone, Eq, PartialEq, Ord, PartialOrd)]
985    pub enum ArbitraryValVec {
986        Void(<Vec<()> as SorobanArbitrary>::Prototype),
987        Bool(<Vec<bool> as SorobanArbitrary>::Prototype),
988        Error(<Vec<Error> as SorobanArbitrary>::Prototype),
989        U32(<Vec<u32> as SorobanArbitrary>::Prototype),
990        I32(<Vec<i32> as SorobanArbitrary>::Prototype),
991        U64(<Vec<u64> as SorobanArbitrary>::Prototype),
992        I64(<Vec<i64> as SorobanArbitrary>::Prototype),
993        U128(<Vec<u128> as SorobanArbitrary>::Prototype),
994        I128(<Vec<i128> as SorobanArbitrary>::Prototype),
995        U256(<Vec<U256> as SorobanArbitrary>::Prototype),
996        I256(<Vec<I256> as SorobanArbitrary>::Prototype),
997        Bytes(<Vec<Bytes> as SorobanArbitrary>::Prototype),
998        BytesN(<Vec<BytesN<32>> as SorobanArbitrary>::Prototype),
999        String(<Vec<String> as SorobanArbitrary>::Prototype),
1000        Symbol(<Vec<Symbol> as SorobanArbitrary>::Prototype),
1001        Vec(<Vec<Vec<u32>> as SorobanArbitrary>::Prototype),
1002        Map(<Vec<Map<u32, u32>> as SorobanArbitrary>::Prototype),
1003        Address(<Vec<Address> as SorobanArbitrary>::Prototype),
1004        Timepoint(<Vec<Timepoint> as SorobanArbitrary>::Prototype),
1005        Duration(<Vec<Duration> as SorobanArbitrary>::Prototype),
1006        Val(<Vec<Val> as SorobanArbitrary>::Prototype),
1007    }
1008
1009    impl TryFromVal<Env, ArbitraryValVec> for Val {
1010        type Error = ConversionError;
1011        fn try_from_val(env: &Env, v: &ArbitraryValVec) -> Result<Self, Self::Error> {
1012            Ok(match v {
1013                ArbitraryValVec::Void(v) => {
1014                    let v: Vec<()> = v.into_val(env);
1015                    v.into_val(env)
1016                }
1017                ArbitraryValVec::Bool(v) => {
1018                    let v: Vec<bool> = v.into_val(env);
1019                    v.into_val(env)
1020                }
1021                ArbitraryValVec::Error(v) => {
1022                    let v: Vec<Error> = v.into_val(env);
1023                    v.into_val(env)
1024                }
1025                ArbitraryValVec::U32(v) => {
1026                    let v: Vec<u32> = v.into_val(env);
1027                    v.into_val(env)
1028                }
1029                ArbitraryValVec::I32(v) => {
1030                    let v: Vec<i32> = v.into_val(env);
1031                    v.into_val(env)
1032                }
1033                ArbitraryValVec::U64(v) => {
1034                    let v: Vec<u64> = v.into_val(env);
1035                    v.into_val(env)
1036                }
1037                ArbitraryValVec::I64(v) => {
1038                    let v: Vec<i64> = v.into_val(env);
1039                    v.into_val(env)
1040                }
1041                ArbitraryValVec::U128(v) => {
1042                    let v: Vec<u128> = v.into_val(env);
1043                    v.into_val(env)
1044                }
1045                ArbitraryValVec::I128(v) => {
1046                    let v: Vec<i128> = v.into_val(env);
1047                    v.into_val(env)
1048                }
1049                ArbitraryValVec::U256(v) => {
1050                    let v: Vec<U256> = v.into_val(env);
1051                    v.into_val(env)
1052                }
1053                ArbitraryValVec::I256(v) => {
1054                    let v: Vec<I256> = v.into_val(env);
1055                    v.into_val(env)
1056                }
1057                ArbitraryValVec::Bytes(v) => {
1058                    let v: Vec<Bytes> = v.into_val(env);
1059                    v.into_val(env)
1060                }
1061                ArbitraryValVec::BytesN(v) => {
1062                    let v: Vec<BytesN<32>> = v.into_val(env);
1063                    v.into_val(env)
1064                }
1065                ArbitraryValVec::String(v) => {
1066                    let v: Vec<String> = v.into_val(env);
1067                    v.into_val(env)
1068                }
1069                ArbitraryValVec::Symbol(v) => {
1070                    let v: Vec<Symbol> = v.into_val(env);
1071                    v.into_val(env)
1072                }
1073                ArbitraryValVec::Vec(v) => {
1074                    let v: Vec<Vec<u32>> = v.into_val(env);
1075                    v.into_val(env)
1076                }
1077                ArbitraryValVec::Map(v) => {
1078                    let v: Vec<Map<u32, u32>> = v.into_val(env);
1079                    v.into_val(env)
1080                }
1081                ArbitraryValVec::Address(v) => {
1082                    let v: Vec<Address> = v.into_val(env);
1083                    v.into_val(env)
1084                }
1085                ArbitraryValVec::Timepoint(v) => {
1086                    let v: Vec<Timepoint> = v.into_val(env);
1087                    v.into_val(env)
1088                }
1089                ArbitraryValVec::Duration(v) => {
1090                    let v: Vec<Duration> = v.into_val(env);
1091                    v.into_val(env)
1092                }
1093                ArbitraryValVec::Val(v) => {
1094                    let v: Vec<Val> = v.into_val(env);
1095                    v.into_val(env)
1096                }
1097            })
1098        }
1099    }
1100
1101    #[derive(Arbitrary, Debug, Clone, Eq, PartialEq, Ord, PartialOrd)]
1102    pub enum ArbitraryValMap {
1103        VoidToVoid(<Map<(), ()> as SorobanArbitrary>::Prototype),
1104        BoolToBool(<Map<bool, bool> as SorobanArbitrary>::Prototype),
1105        ErrorToError(<Map<Error, Error> as SorobanArbitrary>::Prototype),
1106        U32ToU32(<Map<u32, u32> as SorobanArbitrary>::Prototype),
1107        I32ToI32(<Map<i32, i32> as SorobanArbitrary>::Prototype),
1108        U64ToU64(<Map<u64, u64> as SorobanArbitrary>::Prototype),
1109        I64ToI64(<Map<i64, i64> as SorobanArbitrary>::Prototype),
1110        U128ToU128(<Map<u128, u128> as SorobanArbitrary>::Prototype),
1111        I128ToI128(<Map<i128, i128> as SorobanArbitrary>::Prototype),
1112        U256ToU256(<Map<U256, U256> as SorobanArbitrary>::Prototype),
1113        I256ToI256(<Map<I256, I256> as SorobanArbitrary>::Prototype),
1114        BytesToBytes(<Map<Bytes, Bytes> as SorobanArbitrary>::Prototype),
1115        BytesNToBytesN(<Map<BytesN<32>, BytesN<32>> as SorobanArbitrary>::Prototype),
1116        StringToString(<Map<String, String> as SorobanArbitrary>::Prototype),
1117        SymbolToSymbol(<Map<Symbol, Symbol> as SorobanArbitrary>::Prototype),
1118        VecToVec(<Map<Vec<u32>, Vec<u32>> as SorobanArbitrary>::Prototype),
1119        MapToMap(<Map<Map<u32, u32>, Map<u32, u32>> as SorobanArbitrary>::Prototype),
1120        AddressToAddress(<Map<Address, Address> as SorobanArbitrary>::Prototype),
1121        TimepointToTimepoint(<Map<Timepoint, Timepoint> as SorobanArbitrary>::Prototype),
1122        DurationToDuration(<Map<Duration, Duration> as SorobanArbitrary>::Prototype),
1123        ValToVal(<Map<Val, Val> as SorobanArbitrary>::Prototype),
1124        OptionToOption(<Map<Option<u32>, Option<u32>> as SorobanArbitrary>::Prototype),
1125    }
1126
1127    impl TryFromVal<Env, ArbitraryValMap> for Val {
1128        type Error = ConversionError;
1129        fn try_from_val(env: &Env, v: &ArbitraryValMap) -> Result<Self, Self::Error> {
1130            Ok(match v {
1131                ArbitraryValMap::VoidToVoid(v) => {
1132                    let v: Map<(), ()> = v.into_val(env);
1133                    v.into_val(env)
1134                }
1135                ArbitraryValMap::BoolToBool(v) => {
1136                    let v: Map<bool, bool> = v.into_val(env);
1137                    v.into_val(env)
1138                }
1139                ArbitraryValMap::ErrorToError(v) => {
1140                    let v: Map<Error, Error> = v.into_val(env);
1141                    v.into_val(env)
1142                }
1143                ArbitraryValMap::U32ToU32(v) => {
1144                    let v: Map<u32, u32> = v.into_val(env);
1145                    v.into_val(env)
1146                }
1147                ArbitraryValMap::I32ToI32(v) => {
1148                    let v: Map<i32, i32> = v.into_val(env);
1149                    v.into_val(env)
1150                }
1151                ArbitraryValMap::U64ToU64(v) => {
1152                    let v: Map<u64, u64> = v.into_val(env);
1153                    v.into_val(env)
1154                }
1155                ArbitraryValMap::I64ToI64(v) => {
1156                    let v: Map<i64, i64> = v.into_val(env);
1157                    v.into_val(env)
1158                }
1159                ArbitraryValMap::U128ToU128(v) => {
1160                    let v: Map<u128, u128> = v.into_val(env);
1161                    v.into_val(env)
1162                }
1163                ArbitraryValMap::I128ToI128(v) => {
1164                    let v: Map<i128, i128> = v.into_val(env);
1165                    v.into_val(env)
1166                }
1167                ArbitraryValMap::U256ToU256(v) => {
1168                    let v: Map<U256, U256> = v.into_val(env);
1169                    v.into_val(env)
1170                }
1171                ArbitraryValMap::I256ToI256(v) => {
1172                    let v: Map<I256, I256> = v.into_val(env);
1173                    v.into_val(env)
1174                }
1175                ArbitraryValMap::BytesToBytes(v) => {
1176                    let v: Map<Bytes, Bytes> = v.into_val(env);
1177                    v.into_val(env)
1178                }
1179                ArbitraryValMap::BytesNToBytesN(v) => {
1180                    let v: Map<BytesN<32>, BytesN<32>> = v.into_val(env);
1181                    v.into_val(env)
1182                }
1183                ArbitraryValMap::StringToString(v) => {
1184                    let v: Map<String, String> = v.into_val(env);
1185                    v.into_val(env)
1186                }
1187                ArbitraryValMap::SymbolToSymbol(v) => {
1188                    let v: Map<Symbol, Symbol> = v.into_val(env);
1189                    v.into_val(env)
1190                }
1191                ArbitraryValMap::VecToVec(v) => {
1192                    let v: Map<Vec<u32>, Vec<u32>> = v.into_val(env);
1193                    v.into_val(env)
1194                }
1195                ArbitraryValMap::MapToMap(v) => {
1196                    let v: Map<Map<u32, u32>, Map<u32, u32>> = v.into_val(env);
1197                    v.into_val(env)
1198                }
1199                ArbitraryValMap::AddressToAddress(v) => {
1200                    let v: Map<Address, Address> = v.into_val(env);
1201                    v.into_val(env)
1202                }
1203                ArbitraryValMap::TimepointToTimepoint(v) => {
1204                    let v: Map<Timepoint, Timepoint> = v.into_val(env);
1205                    v.into_val(env)
1206                }
1207                ArbitraryValMap::DurationToDuration(v) => {
1208                    let v: Map<Duration, Duration> = v.into_val(env);
1209                    v.into_val(env)
1210                }
1211                ArbitraryValMap::ValToVal(v) => {
1212                    let v: Map<Val, Val> = v.into_val(env);
1213                    v.into_val(env)
1214                }
1215                ArbitraryValMap::OptionToOption(v) => {
1216                    let v: Map<Option<u32>, Option<u32>> = v.into_val(env);
1217                    v.into_val(env)
1218                }
1219            })
1220        }
1221    }
1222
1223    #[derive(Arbitrary, Debug, Clone, Eq, PartialEq, Ord, PartialOrd)]
1224    pub enum ArbitraryValOption {
1225        Void(<Option<()> as SorobanArbitrary>::Prototype),
1226        Bool(<Option<bool> as SorobanArbitrary>::Prototype),
1227        Error(<Option<Error> as SorobanArbitrary>::Prototype),
1228        U32(<Option<u32> as SorobanArbitrary>::Prototype),
1229        I32(<Option<i32> as SorobanArbitrary>::Prototype),
1230        U64(<Option<u64> as SorobanArbitrary>::Prototype),
1231        I64(<Option<i64> as SorobanArbitrary>::Prototype),
1232        U128(<Option<u128> as SorobanArbitrary>::Prototype),
1233        I128(<Option<i128> as SorobanArbitrary>::Prototype),
1234        U256(<Option<U256> as SorobanArbitrary>::Prototype),
1235        I256(<Option<I256> as SorobanArbitrary>::Prototype),
1236        Bytes(<Option<Bytes> as SorobanArbitrary>::Prototype),
1237        BytesN(<Option<BytesN<32>> as SorobanArbitrary>::Prototype),
1238        String(<Option<String> as SorobanArbitrary>::Prototype),
1239        Symbol(<Option<Symbol> as SorobanArbitrary>::Prototype),
1240        Vec(<Option<Vec<u32>> as SorobanArbitrary>::Prototype),
1241        Map(<Option<Map<u32, u32>> as SorobanArbitrary>::Prototype),
1242        Address(<Option<Address> as SorobanArbitrary>::Prototype),
1243        Timepoint(<Option<Timepoint> as SorobanArbitrary>::Prototype),
1244        Duration(<Option<Duration> as SorobanArbitrary>::Prototype),
1245        Val(Box<<Option<Val> as SorobanArbitrary>::Prototype>),
1246    }
1247
1248    impl TryFromVal<Env, ArbitraryValOption> for Val {
1249        type Error = ConversionError;
1250        fn try_from_val(env: &Env, v: &ArbitraryValOption) -> Result<Self, Self::Error> {
1251            Ok(match v {
1252                ArbitraryValOption::Void(v) => {
1253                    let v: Option<()> = v.into_val(env);
1254                    v.into_val(env)
1255                }
1256                ArbitraryValOption::Bool(v) => {
1257                    let v: Option<bool> = v.into_val(env);
1258                    v.into_val(env)
1259                }
1260                ArbitraryValOption::Error(v) => {
1261                    let v: Option<Error> = v.into_val(env);
1262                    v.into_val(env)
1263                }
1264                ArbitraryValOption::U32(v) => {
1265                    let v: Option<u32> = v.into_val(env);
1266                    v.into_val(env)
1267                }
1268                ArbitraryValOption::I32(v) => {
1269                    let v: Option<i32> = v.into_val(env);
1270                    v.into_val(env)
1271                }
1272                ArbitraryValOption::U64(v) => {
1273                    let v: Option<u64> = v.into_val(env);
1274                    v.into_val(env)
1275                }
1276                ArbitraryValOption::I64(v) => {
1277                    let v: Option<i64> = v.into_val(env);
1278                    v.into_val(env)
1279                }
1280                ArbitraryValOption::U128(v) => {
1281                    let v: Option<u128> = v.into_val(env);
1282                    v.into_val(env)
1283                }
1284                ArbitraryValOption::I128(v) => {
1285                    let v: Option<i128> = v.into_val(env);
1286                    v.into_val(env)
1287                }
1288                ArbitraryValOption::U256(v) => {
1289                    let v: Option<U256> = v.into_val(env);
1290                    v.into_val(env)
1291                }
1292                ArbitraryValOption::I256(v) => {
1293                    let v: Option<I256> = v.into_val(env);
1294                    v.into_val(env)
1295                }
1296                ArbitraryValOption::Bytes(v) => {
1297                    let v: Option<Bytes> = v.into_val(env);
1298                    v.into_val(env)
1299                }
1300                ArbitraryValOption::BytesN(v) => {
1301                    let v: Option<BytesN<32>> = v.into_val(env);
1302                    v.into_val(env)
1303                }
1304                ArbitraryValOption::String(v) => {
1305                    let v: Option<String> = v.into_val(env);
1306                    v.into_val(env)
1307                }
1308                ArbitraryValOption::Symbol(v) => {
1309                    let v: Option<Symbol> = v.into_val(env);
1310                    v.into_val(env)
1311                }
1312                ArbitraryValOption::Vec(v) => {
1313                    let v: Option<Vec<u32>> = v.into_val(env);
1314                    v.into_val(env)
1315                }
1316                ArbitraryValOption::Map(v) => {
1317                    let v: Option<Map<u32, u32>> = v.into_val(env);
1318                    v.into_val(env)
1319                }
1320                ArbitraryValOption::Address(v) => {
1321                    let v: Option<Address> = v.into_val(env);
1322                    v.into_val(env)
1323                }
1324                ArbitraryValOption::Timepoint(v) => {
1325                    let v: Option<Timepoint> = v.into_val(env);
1326                    v.into_val(env)
1327                }
1328                ArbitraryValOption::Duration(v) => {
1329                    let v: Option<Duration> = v.into_val(env);
1330                    v.into_val(env)
1331                }
1332                ArbitraryValOption::Val(v) => {
1333                    let v: Option<Val> = (**v).into_val(env);
1334                    v.into_val(env)
1335                }
1336            })
1337        }
1338    }
1339}
1340
1341/// Additional tools for writing fuzz tests.
1342mod fuzz_test_helpers {
1343    use soroban_env_host::testutils::call_with_suppressed_panic_hook;
1344
1345    /// Catch panics within a fuzz test.
1346    ///
1347    /// The `cargo-fuzz` test harness turns panics into test failures,
1348    /// immediately aborting the process.
1349    ///
1350    /// This function catches panics while temporarily disabling the
1351    /// `cargo-fuzz` panic handler.
1352    ///
1353    /// # Example
1354    ///
1355    /// ```
1356    /// # macro_rules! fuzz_target {
1357    /// #     (|$data:ident: $dty: ty| $body:block) => { };
1358    /// # }
1359    /// # struct ExampleContract;
1360    /// # impl ExampleContract {
1361    /// #   fn new(e: &soroban_sdk::Env, b: &soroban_sdk::BytesN<32>) { }
1362    /// #   fn deposit(&self, a: soroban_sdk::Address, n: i128) { }
1363    /// # }
1364    /// use soroban_sdk::{Address, Env};
1365    /// use soroban_sdk::testutils::arbitrary::{Arbitrary, SorobanArbitrary};
1366    ///
1367    /// #[derive(Arbitrary, Debug)]
1368    /// struct FuzzDeposit {
1369    ///     deposit_amount: i128,
1370    ///     deposit_address: <Address as SorobanArbitrary>::Prototype,
1371    /// }
1372    ///
1373    /// fuzz_target!(|input: FuzzDeposit| {
1374    ///     let env = Env::default();
1375    ///
1376    ///     let contract = ExampleContract::new(env, &env.register_contract(None, ExampleContract {}));
1377    ///
1378    ///     let addresses: Address = input.deposit_address.into_val(&env);
1379    ///     let r = contract.try_deposit(deposit_address, input.deposit_amount);
1380    /// });
1381    /// ```
1382    #[deprecated(note = "use [Env::try_invoke] or the try_ functions on a contract client")]
1383    pub fn fuzz_catch_panic<F, R>(f: F) -> std::thread::Result<R>
1384    where
1385        F: FnOnce() -> R,
1386    {
1387        call_with_suppressed_panic_hook(std::panic::AssertUnwindSafe(f))
1388    }
1389}
1390
1391#[cfg(test)]
1392mod tests {
1393    use super::*;
1394    use crate::{
1395        Address, Bytes, BytesN, Duration, Error, Map, String, Symbol, Timepoint, Val, Vec, I256,
1396        U256,
1397    };
1398    use crate::{Env, IntoVal};
1399    use arbitrary::{Arbitrary, Unstructured};
1400    use rand::{RngCore, SeedableRng};
1401
1402    fn run_test<T>()
1403    where
1404        T: SorobanArbitrary,
1405        T::Prototype: for<'a> Arbitrary<'a>,
1406    {
1407        let env = Env::default();
1408        let mut rng = rand::rngs::StdRng::seed_from_u64(0);
1409        let mut rng_data = [0u8; 64];
1410
1411        for _ in 0..100 {
1412            rng.fill_bytes(&mut rng_data);
1413            let mut unstructured = Unstructured::new(&rng_data);
1414            loop {
1415                match T::Prototype::arbitrary(&mut unstructured) {
1416                    Ok(input) => {
1417                        let _val: T = input.into_val(&env);
1418                        break;
1419                    }
1420                    Err(_) => {}
1421                }
1422            }
1423        }
1424    }
1425
1426    #[test]
1427    fn test_unit() {
1428        run_test::<()>()
1429    }
1430
1431    #[test]
1432    fn test_bool() {
1433        run_test::<bool>()
1434    }
1435
1436    #[test]
1437    fn test_u32() {
1438        run_test::<u32>()
1439    }
1440
1441    #[test]
1442    fn test_i32() {
1443        run_test::<i32>()
1444    }
1445
1446    #[test]
1447    fn test_u64() {
1448        run_test::<u64>()
1449    }
1450
1451    #[test]
1452    fn test_i64() {
1453        run_test::<i64>()
1454    }
1455
1456    #[test]
1457    fn test_u128() {
1458        run_test::<u128>()
1459    }
1460
1461    #[test]
1462    fn test_i128() {
1463        run_test::<i128>()
1464    }
1465
1466    #[test]
1467    fn test_u256() {
1468        run_test::<U256>()
1469    }
1470
1471    #[test]
1472    fn test_i256() {
1473        run_test::<I256>()
1474    }
1475
1476    #[test]
1477    fn test_bytes() {
1478        run_test::<Bytes>()
1479    }
1480
1481    #[test]
1482    fn test_string() {
1483        run_test::<String>()
1484    }
1485
1486    #[test]
1487    fn test_bytes_n() {
1488        run_test::<BytesN<32>>()
1489    }
1490
1491    #[test]
1492    fn test_symbol() {
1493        run_test::<Symbol>()
1494    }
1495
1496    #[test]
1497    fn test_address() {
1498        run_test::<Address>()
1499    }
1500
1501    #[test]
1502    fn test_val() {
1503        run_test::<Val>()
1504    }
1505
1506    #[test]
1507    fn test_vec_void() {
1508        run_test::<Vec<()>>()
1509    }
1510
1511    #[test]
1512    fn test_vec_bool() {
1513        run_test::<Vec<bool>>()
1514    }
1515
1516    #[test]
1517    fn test_vec_error() {
1518        run_test::<Vec<Error>>()
1519    }
1520
1521    #[test]
1522    fn test_vec_u32() {
1523        run_test::<Vec<u32>>()
1524    }
1525
1526    #[test]
1527    fn test_vec_i32() {
1528        run_test::<Vec<i32>>()
1529    }
1530
1531    #[test]
1532    fn test_vec_u64() {
1533        run_test::<Vec<u64>>()
1534    }
1535
1536    #[test]
1537    fn test_vec_i64() {
1538        run_test::<Vec<i64>>()
1539    }
1540
1541    #[test]
1542    fn test_vec_u128() {
1543        run_test::<Vec<u128>>()
1544    }
1545
1546    #[test]
1547    fn test_vec_i128() {
1548        run_test::<Vec<i128>>()
1549    }
1550
1551    #[test]
1552    fn test_vec_u256() {
1553        run_test::<Vec<U256>>()
1554    }
1555
1556    #[test]
1557    fn test_vec_i256() {
1558        run_test::<Vec<I256>>()
1559    }
1560
1561    #[test]
1562    fn test_vec_bytes() {
1563        run_test::<Vec<Bytes>>()
1564    }
1565
1566    #[test]
1567    fn test_vec_bytes_n() {
1568        run_test::<Vec<BytesN<32>>>()
1569    }
1570
1571    #[test]
1572    fn test_vec_string() {
1573        run_test::<Vec<String>>()
1574    }
1575
1576    #[test]
1577    fn test_vec_symbol() {
1578        run_test::<Vec<Symbol>>()
1579    }
1580
1581    #[test]
1582    fn test_vec_vec_u32() {
1583        run_test::<Vec<Vec<u32>>>()
1584    }
1585
1586    #[test]
1587    fn test_vec_vec_bytes() {
1588        run_test::<Vec<Vec<Bytes>>>()
1589    }
1590
1591    #[test]
1592    fn test_vec_timepoint() {
1593        run_test::<Vec<Timepoint>>()
1594    }
1595
1596    #[test]
1597    fn test_vec_duration() {
1598        run_test::<Vec<Duration>>()
1599    }
1600
1601    #[test]
1602    fn test_vec_map_u32() {
1603        run_test::<Vec<Map<u32, u32>>>()
1604    }
1605
1606    #[test]
1607    fn test_vec_address() {
1608        run_test::<Vec<Address>>()
1609    }
1610
1611    #[test]
1612    fn test_vec_val() {
1613        run_test::<Vec<Val>>()
1614    }
1615
1616    #[test]
1617    fn test_map_void() {
1618        run_test::<Map<(), ()>>()
1619    }
1620
1621    #[test]
1622    fn test_map_bool() {
1623        run_test::<Map<bool, bool>>()
1624    }
1625
1626    #[test]
1627    fn test_map_error() {
1628        run_test::<Map<Error, Error>>()
1629    }
1630
1631    #[test]
1632    fn test_map_u32() {
1633        run_test::<Map<u32, Vec<u32>>>()
1634    }
1635
1636    #[test]
1637    fn test_map_i32() {
1638        run_test::<Map<i32, Vec<i32>>>()
1639    }
1640
1641    #[test]
1642    fn test_map_u64() {
1643        run_test::<Map<u64, Vec<u64>>>()
1644    }
1645
1646    #[test]
1647    fn test_map_i64() {
1648        run_test::<Map<i64, Vec<i64>>>()
1649    }
1650
1651    #[test]
1652    fn test_map_u128() {
1653        run_test::<Map<u128, Vec<u128>>>()
1654    }
1655
1656    #[test]
1657    fn test_map_i128() {
1658        run_test::<Map<i128, Vec<i128>>>()
1659    }
1660
1661    #[test]
1662    fn test_map_u256() {
1663        run_test::<Map<U256, Vec<U256>>>()
1664    }
1665
1666    #[test]
1667    fn test_map_i256() {
1668        run_test::<Map<I256, Vec<I256>>>()
1669    }
1670
1671    #[test]
1672    fn test_map_bytes() {
1673        run_test::<Map<Bytes, Bytes>>()
1674    }
1675
1676    #[test]
1677    fn test_map_bytes_n() {
1678        run_test::<Map<BytesN<32>, Bytes>>()
1679    }
1680
1681    #[test]
1682    fn test_map_string() {
1683        run_test::<Map<String, String>>()
1684    }
1685
1686    #[test]
1687    fn test_map_symbol() {
1688        run_test::<Map<Symbol, Symbol>>()
1689    }
1690
1691    #[test]
1692    fn test_map_vec_u32() {
1693        run_test::<Map<Vec<u32>, Vec<u32>>>()
1694    }
1695
1696    #[test]
1697    fn test_map_vec_bytes() {
1698        run_test::<Map<Vec<Bytes>, Vec<Bytes>>>()
1699    }
1700
1701    #[test]
1702    fn test_map_timepoint() {
1703        run_test::<Map<Timepoint, Timepoint>>()
1704    }
1705
1706    #[test]
1707    fn test_map_duration() {
1708        run_test::<Map<Duration, Duration>>()
1709    }
1710
1711    fn test_map_map_u32() {
1712        run_test::<Map<Map<u32, u32>, Map<u32, u32>>>()
1713    }
1714
1715    #[test]
1716    fn test_map_address() {
1717        run_test::<Map<Address, Address>>()
1718    }
1719
1720    #[test]
1721    fn test_map_val() {
1722        run_test::<Map<Val, Val>>()
1723    }
1724
1725    #[test]
1726    fn test_timepoint() {
1727        run_test::<Timepoint>()
1728    }
1729
1730    #[test]
1731    fn test_duration() {
1732        run_test::<Duration>()
1733    }
1734
1735    #[test]
1736    fn test_tuples() {
1737        run_test::<(u32,)>();
1738        run_test::<(u32, u32)>();
1739        run_test::<(u32, u32, u32)>();
1740        run_test::<(u32, u32, u32, u32)>();
1741        run_test::<(u32, u32, u32, u32, u32)>();
1742        run_test::<(u32, u32, u32, u32, u32, u32)>();
1743        run_test::<(u32, u32, u32, u32, u32, u32, u32)>();
1744        run_test::<(u32, u32, u32, u32, u32, u32, u32, u32)>();
1745        run_test::<(u32, u32, u32, u32, u32, u32, u32, u32, u32)>();
1746        run_test::<(u32, u32, u32, u32, u32, u32, u32, u32, u32, u32)>();
1747        run_test::<(u32, u32, u32, u32, u32, u32, u32, u32, u32, u32, u32)>();
1748        run_test::<(u32, u32, u32, u32, u32, u32, u32, u32, u32, u32, u32, u32)>();
1749
1750        run_test::<(u32, Address, Vec<Timepoint>, Map<Duration, u64>)>();
1751    }
1752
1753    #[test]
1754    fn test_option() {
1755        run_test::<Option<u32>>();
1756        run_test::<Option<Vec<u32>>>();
1757    }
1758
1759    // Test that sometimes generated vecs have the wrong element types.
1760    #[test]
1761    fn test_vec_wrong_types() {
1762        // These number are tuned for StdRng.
1763        // If StdRng ever changes the test could break.
1764        let iterations = 1000;
1765        let seed = 3;
1766        let acceptable_ratio = 900;
1767
1768        let (mut seen_good, mut seen_bad, mut seen_empty) = (0, 0, 0);
1769
1770        let env = Env::default();
1771        let mut rng = rand::rngs::StdRng::seed_from_u64(seed);
1772        let mut rng_data = [0u8; 64];
1773
1774        for _ in 0..iterations {
1775            rng.fill_bytes(&mut rng_data);
1776            let mut unstructured = Unstructured::new(&rng_data);
1777            let input = <Vec<u32> as SorobanArbitrary>::Prototype::arbitrary(&mut unstructured)
1778                .expect("SorobanArbitrary");
1779            let vec: Vec<u32> = input.into_val(&env);
1780
1781            let has_good_elts = (0..vec.len()).all(|i| vec.try_get(i).is_ok()) && !vec.is_empty();
1782            // Look for elements that cause an error.
1783            let has_bad_elt = (0..vec.len()).any(|i| vec.try_get(i).is_err());
1784
1785            if has_bad_elt {
1786                seen_bad += 1;
1787            } else if has_good_elts {
1788                seen_good += 1;
1789            } else {
1790                seen_empty += 1;
1791            }
1792        }
1793
1794        assert!(seen_good > 0);
1795        assert!(seen_bad > 0);
1796
1797        // sanity check the ratio of good to bad
1798        assert!(seen_good * seen_empty > seen_bad * acceptable_ratio);
1799    }
1800
1801    // Test that sometimes generated maps have the wrong element types.
1802    #[test]
1803    fn test_map_wrong_types() {
1804        // These number are tuned for StdRng.
1805        // If StdRng ever changes the test could break.
1806        let iterations = 4000;
1807        let seed = 13;
1808        let acceptable_ratio = 900;
1809
1810        let (mut seen_good, mut seen_bad_key, mut seen_bad_value, mut seen_empty) = (0, 0, 0, 0);
1811
1812        let env = Env::default();
1813        let mut rng = rand::rngs::StdRng::seed_from_u64(seed);
1814        let mut rng_data = [0u8; 128];
1815
1816        for _ in 0..iterations {
1817            rng.fill_bytes(&mut rng_data);
1818            let mut unstructured = Unstructured::new(&rng_data);
1819            let input =
1820                <Map<u32, u32> as SorobanArbitrary>::Prototype::arbitrary(&mut unstructured)
1821                    .expect("SorobanArbitrary");
1822            let map: Map<u32, u32> = input.into_val(&env);
1823
1824            // Look for elements that cause an error.
1825            let keys = map.keys();
1826            let values = map.values();
1827
1828            let has_good_keys =
1829                (0..keys.len()).all(|i| keys.try_get(i).is_ok()) && !keys.is_empty();
1830            let has_good_values =
1831                (0..values.len()).all(|i| values.try_get(i).is_ok()) && !keys.is_empty();
1832            let has_bad_key = (0..keys.len()).any(|i| keys.try_get(i).is_err());
1833            let has_bad_value = (0..values.len()).any(|i| values.try_get(i).is_err());
1834
1835            if has_bad_key {
1836                seen_bad_key += 1;
1837            } else if has_bad_value {
1838                seen_bad_value += 1;
1839            } else if has_good_keys && has_good_values {
1840                seen_good += 1;
1841            } else {
1842                seen_empty += 1;
1843            }
1844        }
1845
1846        assert!(seen_good > 0);
1847        assert!(seen_bad_key > 0);
1848        assert!(seen_bad_value > 0);
1849
1850        // sanity check the ratio of good to bad
1851        assert!(seen_good * seen_empty > (seen_bad_key + seen_bad_value) * acceptable_ratio);
1852    }
1853
1854    mod user_defined_types {
1855        use super::run_test;
1856        use crate as soroban_sdk;
1857        use crate::{
1858            Address, Bytes, BytesN, Duration, Error, Map, Symbol, Timepoint, Vec, I256, U256,
1859        };
1860        use soroban_sdk::contracttype;
1861
1862        #[contracttype]
1863        #[derive(Clone, Debug, Eq, PartialEq)]
1864        struct PrivStruct {
1865            count_u: u32,
1866            count_i: i32,
1867            bytes_n: BytesN<32>,
1868            vec: Vec<Bytes>,
1869            map: Map<Bytes, Vec<i32>>,
1870            u256: U256,
1871            i156: I256,
1872            error: Error,
1873            address: Address,
1874            symbol: Symbol,
1875            duration: Duration,
1876            timepoint: Timepoint,
1877            nil: (),
1878            vec_tuple: Vec<(u32, Address)>,
1879            option: Option<u32>,
1880        }
1881
1882        #[test]
1883        fn test_user_defined_priv_struct() {
1884            run_test::<PrivStruct>();
1885        }
1886
1887        #[test]
1888        fn test_option_user_defined_priv_struct() {
1889            run_test::<Option<PrivStruct>>();
1890        }
1891
1892        #[contracttype]
1893        #[derive(Clone, Debug, Eq, PartialEq)]
1894        struct PrivStructPubFields {
1895            pub count_u: u32,
1896            pub count_i: i32,
1897            pub bytes_n: BytesN<32>,
1898            pub vec: Vec<Bytes>,
1899            pub map: Map<Bytes, Vec<i32>>,
1900        }
1901
1902        #[test]
1903        fn test_user_defined_priv_struct_pub_fields() {
1904            run_test::<PrivStructPubFields>();
1905        }
1906
1907        #[contracttype]
1908        #[derive(Clone, Debug, Eq, PartialEq)]
1909        pub struct PubStruct {
1910            count_u: u32,
1911            count_i: i32,
1912            bytes_n: BytesN<32>,
1913            vec: Vec<Bytes>,
1914            map: Map<Bytes, Vec<i32>>,
1915        }
1916
1917        #[test]
1918        fn test_user_defined_pub_struct() {
1919            run_test::<PubStruct>();
1920        }
1921
1922        #[contracttype]
1923        #[derive(Clone, Debug, Eq, PartialEq)]
1924        pub struct PubStructPubFields {
1925            pub count_u: u32,
1926            pub count_i: i32,
1927            pub bytes_n: BytesN<32>,
1928            pub vec: Vec<Bytes>,
1929            pub map: Map<Bytes, Vec<i32>>,
1930        }
1931
1932        #[test]
1933        fn test_user_defined_pubstruct_pub_fields() {
1934            run_test::<PubStructPubFields>();
1935        }
1936
1937        #[contracttype]
1938        #[derive(Clone, Debug, Eq, PartialEq)]
1939        struct PrivTupleStruct(
1940            u32,
1941            i32,
1942            BytesN<32>,
1943            Vec<Bytes>,
1944            Map<Bytes, Vec<i32>>,
1945            Vec<(u32, Address)>,
1946            Option<u32>,
1947        );
1948
1949        #[test]
1950        fn test_user_defined_priv_tuple_struct() {
1951            run_test::<PrivTupleStruct>();
1952        }
1953
1954        #[test]
1955        fn test_option_user_defined_priv_tuple_struct() {
1956            run_test::<Option<PrivTupleStruct>>();
1957        }
1958
1959        #[contracttype]
1960        #[derive(Clone, Debug, Eq, PartialEq)]
1961        struct PrivTupleStructPubFields(
1962            pub u32,
1963            pub i32,
1964            pub BytesN<32>,
1965            pub Vec<Bytes>,
1966            pub Map<Bytes, Vec<i32>>,
1967            pub Vec<(u32, Address)>,
1968        );
1969
1970        #[test]
1971        fn test_user_defined_priv_tuple_struct_pub_fields() {
1972            run_test::<PrivTupleStructPubFields>();
1973        }
1974
1975        #[contracttype]
1976        #[derive(Clone, Debug, Eq, PartialEq)]
1977        pub struct PubTupleStruct(u32, i32, BytesN<32>, Vec<Bytes>, Map<Bytes, Vec<i32>>);
1978
1979        #[test]
1980        fn test_user_defined_pub_tuple_struct() {
1981            run_test::<PubTupleStruct>();
1982        }
1983
1984        #[contracttype]
1985        #[derive(Clone, Debug, Eq, PartialEq)]
1986        pub struct PubTupleStructPubFields(
1987            pub u32,
1988            pub i32,
1989            pub BytesN<32>,
1990            pub Vec<Bytes>,
1991            pub Map<Bytes, Vec<i32>>,
1992            pub Vec<(u32, Address)>,
1993        );
1994
1995        #[test]
1996        fn test_user_defined_pub_tuple_struct_pub_fields() {
1997            run_test::<PubTupleStructPubFields>();
1998        }
1999
2000        #[contracttype]
2001        #[derive(Clone, Debug, Eq, PartialEq)]
2002        pub(crate) struct PubCrateStruct(u32);
2003
2004        #[test]
2005        fn test_user_defined_pub_crate_struct() {
2006            run_test::<PubCrateStruct>();
2007        }
2008
2009        #[contracttype]
2010        #[derive(Clone, Debug, Eq, PartialEq)]
2011        enum PrivEnum {
2012            A(u32),
2013            Aa(u32, u32),
2014            C,
2015            D,
2016            E(Vec<(u32, Address)>),
2017            F(Option<u32>),
2018        }
2019
2020        #[test]
2021        fn test_user_defined_priv_enum() {
2022            run_test::<PrivEnum>();
2023        }
2024
2025        #[test]
2026        fn test_option_user_defined_priv_enum() {
2027            run_test::<Option<PrivEnum>>();
2028        }
2029
2030        #[contracttype]
2031        #[derive(Clone, Debug, Eq, PartialEq)]
2032        pub enum PubEnum {
2033            A(u32),
2034            C,
2035            D,
2036        }
2037
2038        #[test]
2039        fn test_user_defined_pub_enum() {
2040            run_test::<PubEnum>();
2041        }
2042
2043        #[contracttype]
2044        #[derive(Clone, Debug, Eq, PartialEq)]
2045        pub(crate) enum PubCrateEnum {
2046            A(u32),
2047            C,
2048            D,
2049        }
2050
2051        #[test]
2052        fn test_user_defined_pub_crate_enum() {
2053            run_test::<PubCrateEnum>();
2054        }
2055
2056        #[contracttype]
2057        #[derive(Copy, Clone, Debug, Eq, PartialEq)]
2058        enum PrivEnumInt {
2059            A = 1,
2060            C = 2,
2061            D = 3,
2062        }
2063
2064        #[test]
2065        fn test_user_defined_priv_enum_int() {
2066            run_test::<PrivEnumInt>();
2067        }
2068
2069        #[contracttype]
2070        #[derive(Copy, Clone, Debug, Eq, PartialEq)]
2071        pub enum PubEnumInt {
2072            A = 1,
2073            C = 2,
2074            D = 3,
2075        }
2076
2077        #[test]
2078        fn test_user_defined_pub_enum_int() {
2079            run_test::<PubEnumInt>();
2080        }
2081
2082        #[test]
2083        fn test_declared_inside_a_fn() {
2084            #[contracttype]
2085            struct Foo {
2086                a: u32,
2087            }
2088
2089            #[contracttype]
2090            enum Bar {
2091                Baz,
2092                Qux,
2093            }
2094
2095            run_test::<Foo>();
2096            run_test::<Bar>();
2097        }
2098
2099        fn test_structs_and_enums_inside_tuples() {
2100            #[contracttype]
2101            struct Foo(u32);
2102
2103            #[contracttype]
2104            enum Bar {
2105                Baz,
2106            }
2107
2108            run_test::<(Foo, Bar)>();
2109        }
2110    }
2111}