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        Address, Bytes, BytesN, Duration, Map, String, Symbol, Timepoint, Val, Vec, I256, U256,
324    };
325
326    use std::string::String as RustString;
327    use std::vec::Vec as RustVec;
328
329    //////////////////////////////////
330
331    #[derive(Arbitrary, Debug, Clone, Eq, PartialEq, Ord, PartialOrd)]
332    pub struct ArbitraryOption<T>(Option<T>);
333
334    impl<T> SorobanArbitrary for Option<T>
335    where
336        T: SorobanArbitrary,
337        Val: TryFromVal<Env, T>,
338    {
339        type Prototype = ArbitraryOption<T::Prototype>;
340    }
341
342    impl<T> TryFromVal<Env, ArbitraryOption<T::Prototype>> for Option<T>
343    where
344        T: SorobanArbitrary,
345    {
346        type Error = ConversionError;
347        fn try_from_val(env: &Env, v: &ArbitraryOption<T::Prototype>) -> Result<Self, Self::Error> {
348            match v.0 {
349                Some(ref t) => Ok(Some(t.into_val(env))),
350                None => Ok(None),
351            }
352        }
353    }
354
355    //////////////////////////////////
356
357    #[derive(Arbitrary, Debug, Clone, Eq, PartialEq, Ord, PartialOrd)]
358    pub struct ArbitraryU256 {
359        parts: (u64, u64, u64, u64),
360    }
361
362    impl SorobanArbitrary for U256 {
363        type Prototype = ArbitraryU256;
364    }
365
366    impl TryFromVal<Env, ArbitraryU256> for U256 {
367        type Error = ConversionError;
368        fn try_from_val(env: &Env, v: &ArbitraryU256) -> Result<Self, Self::Error> {
369            let v = ScVal::U256(UInt256Parts {
370                hi_hi: v.parts.0,
371                hi_lo: v.parts.1,
372                lo_hi: v.parts.2,
373                lo_lo: v.parts.3,
374            });
375            let v = Val::try_from_val(env, &v)?;
376            v.try_into_val(env)
377        }
378    }
379
380    //////////////////////////////////
381
382    #[derive(Arbitrary, Debug, Clone, Eq, PartialEq, Ord, PartialOrd)]
383    pub struct ArbitraryI256 {
384        parts: (i64, u64, u64, u64),
385    }
386
387    impl SorobanArbitrary for I256 {
388        type Prototype = ArbitraryI256;
389    }
390
391    impl TryFromVal<Env, ArbitraryI256> for I256 {
392        type Error = ConversionError;
393        fn try_from_val(env: &Env, v: &ArbitraryI256) -> Result<Self, Self::Error> {
394            let v = ScVal::I256(Int256Parts {
395                hi_hi: v.parts.0,
396                hi_lo: v.parts.1,
397                lo_hi: v.parts.2,
398                lo_lo: v.parts.3,
399            });
400            let v = Val::try_from_val(env, &v)?;
401            v.try_into_val(env)
402        }
403    }
404
405    //////////////////////////////////
406
407    #[derive(Arbitrary, Debug, Clone, Eq, PartialEq, Ord, PartialOrd)]
408    pub struct ArbitraryBytes {
409        vec: RustVec<u8>,
410    }
411
412    impl SorobanArbitrary for Bytes {
413        type Prototype = ArbitraryBytes;
414    }
415
416    impl TryFromVal<Env, ArbitraryBytes> for Bytes {
417        type Error = ConversionError;
418        fn try_from_val(env: &Env, v: &ArbitraryBytes) -> Result<Self, Self::Error> {
419            Self::try_from_val(env, &v.vec.as_slice())
420        }
421    }
422
423    //////////////////////////////////
424
425    #[derive(Arbitrary, Debug, Clone, Eq, PartialEq, Ord, PartialOrd)]
426    pub struct ArbitraryString {
427        inner: RustString,
428    }
429
430    impl SorobanArbitrary for String {
431        type Prototype = ArbitraryString;
432    }
433
434    impl TryFromVal<Env, ArbitraryString> for String {
435        type Error = ConversionError;
436        fn try_from_val(env: &Env, v: &ArbitraryString) -> Result<Self, Self::Error> {
437            Self::try_from_val(env, &v.inner.as_str())
438        }
439    }
440
441    //////////////////////////////////
442
443    #[derive(Arbitrary, Debug, Clone, Eq, PartialEq, Ord, PartialOrd)]
444    pub struct ArbitraryBytesN<const N: usize> {
445        array: [u8; N],
446    }
447
448    impl<const N: usize> SorobanArbitrary for BytesN<N> {
449        type Prototype = ArbitraryBytesN<N>;
450    }
451
452    impl<const N: usize> TryFromVal<Env, ArbitraryBytesN<N>> for BytesN<N> {
453        type Error = ConversionError;
454        fn try_from_val(env: &Env, v: &ArbitraryBytesN<N>) -> Result<Self, Self::Error> {
455            Self::try_from_val(env, &v.array)
456        }
457    }
458
459    //////////////////////////////////
460
461    #[derive(Debug, Clone, Eq, PartialEq, Ord, PartialOrd)]
462    pub struct ArbitrarySymbol {
463        s: RustString,
464    }
465
466    impl<'a> Arbitrary<'a> for ArbitrarySymbol {
467        fn arbitrary(u: &mut Unstructured<'a>) -> ArbitraryResult<ArbitrarySymbol> {
468            let valid_chars = "_abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
469            let valid_chars = valid_chars.as_bytes();
470            let mut chars = vec![];
471            let len = u.int_in_range(0..=32)?;
472            for _ in 0..len {
473                let ch = u.choose(valid_chars)?;
474                chars.push(*ch);
475            }
476            Ok(ArbitrarySymbol {
477                s: RustString::from_utf8(chars).expect("utf8"),
478            })
479        }
480    }
481
482    impl SorobanArbitrary for Symbol {
483        type Prototype = ArbitrarySymbol;
484    }
485
486    impl TryFromVal<Env, ArbitrarySymbol> for Symbol {
487        type Error = ConversionError;
488        fn try_from_val(env: &Env, v: &ArbitrarySymbol) -> Result<Self, Self::Error> {
489            Self::try_from_val(env, &v.s.as_str())
490        }
491    }
492
493    //////////////////////////////////
494
495    #[derive(Debug, Clone, Eq, PartialEq, Ord, PartialOrd)]
496    pub enum ArbitraryVec<T> {
497        Good(RustVec<T>),
498        // Vec<T> can be constructed with non-T values.
499        Wrong(RustVec<ArbitraryVal>),
500    }
501
502    impl<'a, T> Arbitrary<'a> for ArbitraryVec<T>
503    where
504        T: Arbitrary<'a>,
505    {
506        fn arbitrary(u: &mut Unstructured<'a>) -> ArbitraryResult<ArbitraryVec<T>> {
507            // How frequently we provide ArbitraryVec::Wrong
508            const WRONG_TYPE_RATIO: (u16, u16) = (1, 1000);
509
510            if u.ratio(WRONG_TYPE_RATIO.0, WRONG_TYPE_RATIO.1)? {
511                Ok(ArbitraryVec::Wrong(Arbitrary::arbitrary(u)?))
512            } else {
513                Ok(ArbitraryVec::Good(Arbitrary::arbitrary(u)?))
514            }
515        }
516    }
517
518    impl<T> SorobanArbitrary for Vec<T>
519    where
520        T: SorobanArbitrary,
521    {
522        type Prototype = ArbitraryVec<T::Prototype>;
523    }
524
525    impl<T> TryFromVal<Env, ArbitraryVec<T::Prototype>> for Vec<T>
526    where
527        T: SorobanArbitrary,
528    {
529        type Error = ConversionError;
530        fn try_from_val(env: &Env, v: &ArbitraryVec<T::Prototype>) -> Result<Self, Self::Error> {
531            match v {
532                ArbitraryVec::Good(vec) => {
533                    let mut buf: Vec<T> = Vec::new(env);
534                    for item in vec.iter() {
535                        buf.push_back(item.into_val(env));
536                    }
537                    Ok(buf)
538                }
539                ArbitraryVec::Wrong(vec) => {
540                    let mut buf: Vec<Val> = Vec::new(env);
541                    for item in vec.iter() {
542                        buf.push_back(item.into_val(env));
543                    }
544                    Ok(Vec::<T>::from_val(env, &buf.to_val()))
545                }
546            }
547        }
548    }
549
550    //////////////////////////////////
551
552    #[derive(Debug, Clone, Eq, PartialEq, Ord, PartialOrd)]
553    pub enum ArbitraryMap<K, V> {
554        Good(RustVec<(K, V)>),
555        // Maps can be constructed with non-T K/Vs
556        WrongKey(RustVec<(ArbitraryVal, V)>),
557        WrongValue(RustVec<(K, ArbitraryVal)>),
558    }
559
560    impl<'a, K, V> Arbitrary<'a> for ArbitraryMap<K, V>
561    where
562        K: Arbitrary<'a>,
563        V: Arbitrary<'a>,
564    {
565        fn arbitrary(u: &mut Unstructured<'a>) -> ArbitraryResult<ArbitraryMap<K, V>> {
566            // How frequently we provide ArbitraryMap::Wrong*
567            const WRONG_TYPE_RATIO: (u16, u16) = (1, 1000);
568
569            if u.ratio(WRONG_TYPE_RATIO.0, WRONG_TYPE_RATIO.1)? {
570                if u.arbitrary::<bool>()? {
571                    Ok(ArbitraryMap::WrongKey(Arbitrary::arbitrary(u)?))
572                } else {
573                    Ok(ArbitraryMap::WrongValue(Arbitrary::arbitrary(u)?))
574                }
575            } else {
576                Ok(ArbitraryMap::Good(Arbitrary::arbitrary(u)?))
577            }
578        }
579    }
580
581    impl<K, V> SorobanArbitrary for Map<K, V>
582    where
583        K: SorobanArbitrary,
584        V: SorobanArbitrary,
585    {
586        type Prototype = ArbitraryMap<K::Prototype, V::Prototype>;
587    }
588
589    impl<K, V> TryFromVal<Env, ArbitraryMap<K::Prototype, V::Prototype>> for Map<K, V>
590    where
591        K: SorobanArbitrary,
592        V: SorobanArbitrary,
593    {
594        type Error = ConversionError;
595        fn try_from_val(
596            env: &Env,
597            v: &ArbitraryMap<K::Prototype, V::Prototype>,
598        ) -> Result<Self, Self::Error> {
599            match v {
600                ArbitraryMap::Good(vec) => {
601                    let mut map: Map<K, V> = Map::new(env);
602                    for (k, v) in vec.iter() {
603                        map.set(k.into_val(env), v.into_val(env));
604                    }
605                    Ok(map)
606                }
607                ArbitraryMap::WrongKey(vec) => {
608                    let mut map: Map<Val, V> = Map::new(env);
609                    for (k, v) in vec.iter() {
610                        map.set(k.into_val(env), v.into_val(env));
611                    }
612                    Ok(Map::<K, V>::from_val(env, &map.to_val()))
613                }
614                ArbitraryMap::WrongValue(vec) => {
615                    let mut map: Map<K, Val> = Map::new(env);
616                    for (k, v) in vec.iter() {
617                        map.set(k.into_val(env), v.into_val(env));
618                    }
619                    Ok(Map::<K, V>::from_val(env, &map.to_val()))
620                }
621            }
622        }
623    }
624
625    //////////////////////////////////
626
627    #[derive(Arbitrary, Debug, Clone, Eq, PartialEq, Ord, PartialOrd)]
628    pub struct ArbitraryAddress {
629        inner: [u8; 32],
630    }
631
632    impl SorobanArbitrary for Address {
633        type Prototype = ArbitraryAddress;
634    }
635
636    impl TryFromVal<Env, ArbitraryAddress> for Address {
637        type Error = ConversionError;
638        fn try_from_val(env: &Env, v: &ArbitraryAddress) -> Result<Self, Self::Error> {
639            use crate::env::xdr::{Hash, ScAddress};
640
641            let sc_addr = ScVal::Address(ScAddress::Contract(Hash(v.inner)));
642            Ok(sc_addr.into_val(env))
643        }
644    }
645
646    //////////////////////////////////
647
648    #[derive(Arbitrary, Debug, Clone, Eq, PartialEq, Ord, PartialOrd)]
649    pub struct ArbitraryTimepoint {
650        inner: u64,
651    }
652
653    impl SorobanArbitrary for Timepoint {
654        type Prototype = ArbitraryTimepoint;
655    }
656
657    impl TryFromVal<Env, ArbitraryTimepoint> for Timepoint {
658        type Error = ConversionError;
659        fn try_from_val(env: &Env, v: &ArbitraryTimepoint) -> Result<Self, Self::Error> {
660            let sc_timepoint = ScVal::Timepoint(crate::xdr::TimePoint::from(v.inner));
661            Ok(sc_timepoint.into_val(env))
662        }
663    }
664
665    //////////////////////////////////
666
667    #[derive(Arbitrary, Debug, Clone, Eq, PartialEq, Ord, PartialOrd)]
668    pub struct ArbitraryDuration {
669        inner: u64,
670    }
671
672    impl SorobanArbitrary for Duration {
673        type Prototype = ArbitraryDuration;
674    }
675
676    impl TryFromVal<Env, ArbitraryDuration> for Duration {
677        type Error = ConversionError;
678        fn try_from_val(env: &Env, v: &ArbitraryDuration) -> Result<Self, Self::Error> {
679            let sc_duration = ScVal::Duration(crate::xdr::Duration::from(v.inner));
680            Ok(sc_duration.into_val(env))
681        }
682    }
683}
684
685/// Implementations of `soroban_sdk::testutils::arbitrary::api` for tuples of Soroban types.
686///
687/// The implementation is similar to objects, but macroized.
688mod tuples {
689    use super::api::*;
690    use crate::ConversionError;
691    use crate::{Env, IntoVal, TryFromVal, TryIntoVal, Val};
692    use arbitrary::Arbitrary;
693
694    macro_rules! impl_tuple {
695        ($name: ident, $($ty: ident),+ ) => {
696            #[allow(non_snake_case)] // naming fields T1, etc.
697            #[derive(Arbitrary, Debug, Clone, Eq, PartialEq, Ord, PartialOrd)]
698            pub struct $name<$($ty,)*> {
699                $($ty: $ty,)*
700            }
701
702            impl<$($ty,)*> SorobanArbitrary for ($($ty,)*)
703            where $($ty: SorobanArbitrary + TryIntoVal<Env, Val>,)*
704            {
705                type Prototype = $name<$($ty::Prototype,)*>;
706            }
707
708            impl<$($ty,)*> TryFromVal<Env, $name<$($ty::Prototype,)*>> for ($($ty,)*)
709            where $($ty: SorobanArbitrary,)*
710            {
711                type Error = ConversionError;
712                fn try_from_val(env: &Env, v: &$name<$($ty::Prototype,)*>) -> Result<Self, Self::Error> {
713                    Ok(($(
714                        v.$ty.into_val(env),
715                    )*))
716                }
717            }
718        }
719    }
720
721    impl_tuple!(ArbitraryTuple1, T1);
722    impl_tuple!(ArbitraryTuple2, T1, T2);
723    impl_tuple!(ArbitraryTuple3, T1, T2, T3);
724    impl_tuple!(ArbitraryTuple4, T1, T2, T3, T4);
725    impl_tuple!(ArbitraryTuple5, T1, T2, T3, T4, T5);
726    impl_tuple!(ArbitraryTuple6, T1, T2, T3, T4, T5, T6);
727    impl_tuple!(ArbitraryTuple7, T1, T2, T3, T4, T5, T6, T7);
728    impl_tuple!(ArbitraryTuple8, T1, T2, T3, T4, T5, T6, T7, T8);
729    impl_tuple!(ArbitraryTuple9, T1, T2, T3, T4, T5, T6, T7, T8, T9);
730    impl_tuple!(ArbitraryTuple10, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10);
731    impl_tuple!(
732        ArbitraryTuple11,
733        T1,
734        T2,
735        T3,
736        T4,
737        T5,
738        T6,
739        T7,
740        T8,
741        T9,
742        T10,
743        T11
744    );
745    impl_tuple!(
746        ArbitraryTuple12,
747        T1,
748        T2,
749        T3,
750        T4,
751        T5,
752        T6,
753        T7,
754        T8,
755        T9,
756        T10,
757        T11,
758        T12
759    );
760}
761
762/// Implementations of `soroban_sdk::testutils::arbitrary::api` for `Val`.
763mod composite {
764    use arbitrary::Arbitrary;
765
766    use super::api::*;
767    use crate::ConversionError;
768    use crate::{Env, IntoVal, TryFromVal};
769
770    use super::objects::*;
771    use super::simple::*;
772    use crate::{
773        Address, Bytes, BytesN, Duration, Map, String, Symbol, Timepoint, Val, Vec, I256, U256,
774    };
775
776    #[derive(Arbitrary, Debug, Clone, Eq, PartialEq, Ord, PartialOrd)]
777    pub enum ArbitraryVal {
778        Void,
779        Bool(bool),
780        Error(Error),
781        U32(u32),
782        I32(i32),
783        U64(u64),
784        I64(i64),
785        U128(u128),
786        I128(i128),
787        U256(ArbitraryU256),
788        I256(ArbitraryI256),
789        Bytes(ArbitraryBytes),
790        String(ArbitraryString),
791        Symbol(ArbitrarySymbol),
792        Vec(ArbitraryValVec),
793        Map(ArbitraryValMap),
794        Address(ArbitraryAddress),
795        Timepoint(ArbitraryTimepoint),
796        Duration(ArbitraryDuration),
797        Option(ArbitraryValOption),
798    }
799
800    impl SorobanArbitrary for Val {
801        type Prototype = ArbitraryVal;
802    }
803
804    impl TryFromVal<Env, ArbitraryVal> for Val {
805        type Error = ConversionError;
806        fn try_from_val(env: &Env, v: &ArbitraryVal) -> Result<Self, Self::Error> {
807            Ok(match v {
808                ArbitraryVal::Void => Val::VOID.into(),
809                ArbitraryVal::Bool(v) => v.into_val(env),
810                ArbitraryVal::Error(v) => v.into_val(env),
811                ArbitraryVal::U32(v) => v.into_val(env),
812                ArbitraryVal::I32(v) => v.into_val(env),
813                ArbitraryVal::U64(v) => v.into_val(env),
814                ArbitraryVal::I64(v) => v.into_val(env),
815                ArbitraryVal::U256(v) => {
816                    let v: U256 = v.into_val(env);
817                    v.into_val(env)
818                }
819                ArbitraryVal::I256(v) => {
820                    let v: I256 = v.into_val(env);
821                    v.into_val(env)
822                }
823                ArbitraryVal::U128(v) => v.into_val(env),
824                ArbitraryVal::I128(v) => v.into_val(env),
825                ArbitraryVal::Bytes(v) => {
826                    let v: Bytes = v.into_val(env);
827                    v.into_val(env)
828                }
829                ArbitraryVal::String(v) => {
830                    let v: String = v.into_val(env);
831                    v.into_val(env)
832                }
833                ArbitraryVal::Symbol(v) => {
834                    let v: Symbol = v.into_val(env);
835                    v.into_val(env)
836                }
837                ArbitraryVal::Vec(v) => v.into_val(env),
838                ArbitraryVal::Map(v) => v.into_val(env),
839                ArbitraryVal::Address(v) => {
840                    let v: Address = v.into_val(env);
841                    v.into_val(env)
842                }
843                ArbitraryVal::Timepoint(v) => {
844                    let v: Timepoint = v.into_val(env);
845                    v.into_val(env)
846                }
847                ArbitraryVal::Duration(v) => {
848                    let v: Duration = v.into_val(env);
849                    v.into_val(env)
850                }
851                ArbitraryVal::Option(v) => v.into_val(env),
852            })
853        }
854    }
855
856    #[derive(Arbitrary, Debug, Clone, Eq, PartialEq, Ord, PartialOrd)]
857    pub enum ArbitraryValVec {
858        Void(<Vec<()> as SorobanArbitrary>::Prototype),
859        Bool(<Vec<bool> as SorobanArbitrary>::Prototype),
860        Error(<Vec<Error> as SorobanArbitrary>::Prototype),
861        U32(<Vec<u32> as SorobanArbitrary>::Prototype),
862        I32(<Vec<i32> as SorobanArbitrary>::Prototype),
863        U64(<Vec<u64> as SorobanArbitrary>::Prototype),
864        I64(<Vec<i64> as SorobanArbitrary>::Prototype),
865        U128(<Vec<u128> as SorobanArbitrary>::Prototype),
866        I128(<Vec<i128> as SorobanArbitrary>::Prototype),
867        U256(<Vec<U256> as SorobanArbitrary>::Prototype),
868        I256(<Vec<I256> as SorobanArbitrary>::Prototype),
869        Bytes(<Vec<Bytes> as SorobanArbitrary>::Prototype),
870        BytesN(<Vec<BytesN<32>> as SorobanArbitrary>::Prototype),
871        String(<Vec<String> as SorobanArbitrary>::Prototype),
872        Symbol(<Vec<Symbol> as SorobanArbitrary>::Prototype),
873        Vec(<Vec<Vec<u32>> as SorobanArbitrary>::Prototype),
874        Map(<Vec<Map<u32, u32>> as SorobanArbitrary>::Prototype),
875        Address(<Vec<Address> as SorobanArbitrary>::Prototype),
876        Timepoint(<Vec<Timepoint> as SorobanArbitrary>::Prototype),
877        Duration(<Vec<Duration> as SorobanArbitrary>::Prototype),
878        Val(<Vec<Val> as SorobanArbitrary>::Prototype),
879    }
880
881    impl TryFromVal<Env, ArbitraryValVec> for Val {
882        type Error = ConversionError;
883        fn try_from_val(env: &Env, v: &ArbitraryValVec) -> Result<Self, Self::Error> {
884            Ok(match v {
885                ArbitraryValVec::Void(v) => {
886                    let v: Vec<()> = v.into_val(env);
887                    v.into_val(env)
888                }
889                ArbitraryValVec::Bool(v) => {
890                    let v: Vec<bool> = v.into_val(env);
891                    v.into_val(env)
892                }
893                ArbitraryValVec::Error(v) => {
894                    let v: Vec<Error> = v.into_val(env);
895                    v.into_val(env)
896                }
897                ArbitraryValVec::U32(v) => {
898                    let v: Vec<u32> = v.into_val(env);
899                    v.into_val(env)
900                }
901                ArbitraryValVec::I32(v) => {
902                    let v: Vec<i32> = v.into_val(env);
903                    v.into_val(env)
904                }
905                ArbitraryValVec::U64(v) => {
906                    let v: Vec<u64> = v.into_val(env);
907                    v.into_val(env)
908                }
909                ArbitraryValVec::I64(v) => {
910                    let v: Vec<i64> = v.into_val(env);
911                    v.into_val(env)
912                }
913                ArbitraryValVec::U128(v) => {
914                    let v: Vec<u128> = v.into_val(env);
915                    v.into_val(env)
916                }
917                ArbitraryValVec::I128(v) => {
918                    let v: Vec<i128> = v.into_val(env);
919                    v.into_val(env)
920                }
921                ArbitraryValVec::U256(v) => {
922                    let v: Vec<U256> = v.into_val(env);
923                    v.into_val(env)
924                }
925                ArbitraryValVec::I256(v) => {
926                    let v: Vec<I256> = v.into_val(env);
927                    v.into_val(env)
928                }
929                ArbitraryValVec::Bytes(v) => {
930                    let v: Vec<Bytes> = v.into_val(env);
931                    v.into_val(env)
932                }
933                ArbitraryValVec::BytesN(v) => {
934                    let v: Vec<BytesN<32>> = v.into_val(env);
935                    v.into_val(env)
936                }
937                ArbitraryValVec::String(v) => {
938                    let v: Vec<String> = v.into_val(env);
939                    v.into_val(env)
940                }
941                ArbitraryValVec::Symbol(v) => {
942                    let v: Vec<Symbol> = v.into_val(env);
943                    v.into_val(env)
944                }
945                ArbitraryValVec::Vec(v) => {
946                    let v: Vec<Vec<u32>> = v.into_val(env);
947                    v.into_val(env)
948                }
949                ArbitraryValVec::Map(v) => {
950                    let v: Vec<Map<u32, u32>> = v.into_val(env);
951                    v.into_val(env)
952                }
953                ArbitraryValVec::Address(v) => {
954                    let v: Vec<Address> = v.into_val(env);
955                    v.into_val(env)
956                }
957                ArbitraryValVec::Timepoint(v) => {
958                    let v: Vec<Timepoint> = v.into_val(env);
959                    v.into_val(env)
960                }
961                ArbitraryValVec::Duration(v) => {
962                    let v: Vec<Duration> = v.into_val(env);
963                    v.into_val(env)
964                }
965                ArbitraryValVec::Val(v) => {
966                    let v: Vec<Val> = v.into_val(env);
967                    v.into_val(env)
968                }
969            })
970        }
971    }
972
973    #[derive(Arbitrary, Debug, Clone, Eq, PartialEq, Ord, PartialOrd)]
974    pub enum ArbitraryValMap {
975        VoidToVoid(<Map<(), ()> as SorobanArbitrary>::Prototype),
976        BoolToBool(<Map<bool, bool> as SorobanArbitrary>::Prototype),
977        ErrorToError(<Map<Error, Error> as SorobanArbitrary>::Prototype),
978        U32ToU32(<Map<u32, u32> as SorobanArbitrary>::Prototype),
979        I32ToI32(<Map<i32, i32> as SorobanArbitrary>::Prototype),
980        U64ToU64(<Map<u64, u64> as SorobanArbitrary>::Prototype),
981        I64ToI64(<Map<i64, i64> as SorobanArbitrary>::Prototype),
982        U128ToU128(<Map<u128, u128> as SorobanArbitrary>::Prototype),
983        I128ToI128(<Map<i128, i128> as SorobanArbitrary>::Prototype),
984        U256ToU256(<Map<U256, U256> as SorobanArbitrary>::Prototype),
985        I256ToI256(<Map<I256, I256> as SorobanArbitrary>::Prototype),
986        BytesToBytes(<Map<Bytes, Bytes> as SorobanArbitrary>::Prototype),
987        BytesNToBytesN(<Map<BytesN<32>, BytesN<32>> as SorobanArbitrary>::Prototype),
988        StringToString(<Map<String, String> as SorobanArbitrary>::Prototype),
989        SymbolToSymbol(<Map<Symbol, Symbol> as SorobanArbitrary>::Prototype),
990        VecToVec(<Map<Vec<u32>, Vec<u32>> as SorobanArbitrary>::Prototype),
991        MapToMap(<Map<Map<u32, u32>, Map<u32, u32>> as SorobanArbitrary>::Prototype),
992        AddressToAddress(<Map<Address, Address> as SorobanArbitrary>::Prototype),
993        TimepointToTimepoint(<Map<Timepoint, Timepoint> as SorobanArbitrary>::Prototype),
994        DurationToDuration(<Map<Duration, Duration> as SorobanArbitrary>::Prototype),
995        ValToVal(<Map<Val, Val> as SorobanArbitrary>::Prototype),
996        OptionToOption(<Map<Option<u32>, Option<u32>> as SorobanArbitrary>::Prototype),
997    }
998
999    impl TryFromVal<Env, ArbitraryValMap> for Val {
1000        type Error = ConversionError;
1001        fn try_from_val(env: &Env, v: &ArbitraryValMap) -> Result<Self, Self::Error> {
1002            Ok(match v {
1003                ArbitraryValMap::VoidToVoid(v) => {
1004                    let v: Map<(), ()> = v.into_val(env);
1005                    v.into_val(env)
1006                }
1007                ArbitraryValMap::BoolToBool(v) => {
1008                    let v: Map<bool, bool> = v.into_val(env);
1009                    v.into_val(env)
1010                }
1011                ArbitraryValMap::ErrorToError(v) => {
1012                    let v: Map<Error, Error> = v.into_val(env);
1013                    v.into_val(env)
1014                }
1015                ArbitraryValMap::U32ToU32(v) => {
1016                    let v: Map<u32, u32> = v.into_val(env);
1017                    v.into_val(env)
1018                }
1019                ArbitraryValMap::I32ToI32(v) => {
1020                    let v: Map<i32, i32> = v.into_val(env);
1021                    v.into_val(env)
1022                }
1023                ArbitraryValMap::U64ToU64(v) => {
1024                    let v: Map<u64, u64> = v.into_val(env);
1025                    v.into_val(env)
1026                }
1027                ArbitraryValMap::I64ToI64(v) => {
1028                    let v: Map<i64, i64> = v.into_val(env);
1029                    v.into_val(env)
1030                }
1031                ArbitraryValMap::U128ToU128(v) => {
1032                    let v: Map<u128, u128> = v.into_val(env);
1033                    v.into_val(env)
1034                }
1035                ArbitraryValMap::I128ToI128(v) => {
1036                    let v: Map<i128, i128> = v.into_val(env);
1037                    v.into_val(env)
1038                }
1039                ArbitraryValMap::U256ToU256(v) => {
1040                    let v: Map<U256, U256> = v.into_val(env);
1041                    v.into_val(env)
1042                }
1043                ArbitraryValMap::I256ToI256(v) => {
1044                    let v: Map<I256, I256> = v.into_val(env);
1045                    v.into_val(env)
1046                }
1047                ArbitraryValMap::BytesToBytes(v) => {
1048                    let v: Map<Bytes, Bytes> = v.into_val(env);
1049                    v.into_val(env)
1050                }
1051                ArbitraryValMap::BytesNToBytesN(v) => {
1052                    let v: Map<BytesN<32>, BytesN<32>> = v.into_val(env);
1053                    v.into_val(env)
1054                }
1055                ArbitraryValMap::StringToString(v) => {
1056                    let v: Map<String, String> = v.into_val(env);
1057                    v.into_val(env)
1058                }
1059                ArbitraryValMap::SymbolToSymbol(v) => {
1060                    let v: Map<Symbol, Symbol> = v.into_val(env);
1061                    v.into_val(env)
1062                }
1063                ArbitraryValMap::VecToVec(v) => {
1064                    let v: Map<Vec<u32>, Vec<u32>> = v.into_val(env);
1065                    v.into_val(env)
1066                }
1067                ArbitraryValMap::MapToMap(v) => {
1068                    let v: Map<Map<u32, u32>, Map<u32, u32>> = v.into_val(env);
1069                    v.into_val(env)
1070                }
1071                ArbitraryValMap::AddressToAddress(v) => {
1072                    let v: Map<Address, Address> = v.into_val(env);
1073                    v.into_val(env)
1074                }
1075                ArbitraryValMap::TimepointToTimepoint(v) => {
1076                    let v: Map<Timepoint, Timepoint> = v.into_val(env);
1077                    v.into_val(env)
1078                }
1079                ArbitraryValMap::DurationToDuration(v) => {
1080                    let v: Map<Duration, Duration> = v.into_val(env);
1081                    v.into_val(env)
1082                }
1083                ArbitraryValMap::ValToVal(v) => {
1084                    let v: Map<Val, Val> = v.into_val(env);
1085                    v.into_val(env)
1086                }
1087                ArbitraryValMap::OptionToOption(v) => {
1088                    let v: Map<Option<u32>, Option<u32>> = v.into_val(env);
1089                    v.into_val(env)
1090                }
1091            })
1092        }
1093    }
1094
1095    #[derive(Arbitrary, Debug, Clone, Eq, PartialEq, Ord, PartialOrd)]
1096    pub enum ArbitraryValOption {
1097        Void(<Option<()> as SorobanArbitrary>::Prototype),
1098        Bool(<Option<bool> as SorobanArbitrary>::Prototype),
1099        Error(<Option<Error> as SorobanArbitrary>::Prototype),
1100        U32(<Option<u32> as SorobanArbitrary>::Prototype),
1101        I32(<Option<i32> as SorobanArbitrary>::Prototype),
1102        U64(<Option<u64> as SorobanArbitrary>::Prototype),
1103        I64(<Option<i64> as SorobanArbitrary>::Prototype),
1104        U128(<Option<u128> as SorobanArbitrary>::Prototype),
1105        I128(<Option<i128> as SorobanArbitrary>::Prototype),
1106        U256(<Option<U256> as SorobanArbitrary>::Prototype),
1107        I256(<Option<I256> as SorobanArbitrary>::Prototype),
1108        Bytes(<Option<Bytes> as SorobanArbitrary>::Prototype),
1109        BytesN(<Option<BytesN<32>> as SorobanArbitrary>::Prototype),
1110        String(<Option<String> as SorobanArbitrary>::Prototype),
1111        Symbol(<Option<Symbol> as SorobanArbitrary>::Prototype),
1112        Vec(<Option<Vec<u32>> as SorobanArbitrary>::Prototype),
1113        Map(<Option<Map<u32, u32>> as SorobanArbitrary>::Prototype),
1114        Address(<Option<Address> as SorobanArbitrary>::Prototype),
1115        Timepoint(<Option<Timepoint> as SorobanArbitrary>::Prototype),
1116        Duration(<Option<Duration> as SorobanArbitrary>::Prototype),
1117        Val(Box<<Option<Val> as SorobanArbitrary>::Prototype>),
1118    }
1119
1120    impl TryFromVal<Env, ArbitraryValOption> for Val {
1121        type Error = ConversionError;
1122        fn try_from_val(env: &Env, v: &ArbitraryValOption) -> Result<Self, Self::Error> {
1123            Ok(match v {
1124                ArbitraryValOption::Void(v) => {
1125                    let v: Option<()> = v.into_val(env);
1126                    v.into_val(env)
1127                }
1128                ArbitraryValOption::Bool(v) => {
1129                    let v: Option<bool> = v.into_val(env);
1130                    v.into_val(env)
1131                }
1132                ArbitraryValOption::Error(v) => {
1133                    let v: Option<Error> = v.into_val(env);
1134                    v.into_val(env)
1135                }
1136                ArbitraryValOption::U32(v) => {
1137                    let v: Option<u32> = v.into_val(env);
1138                    v.into_val(env)
1139                }
1140                ArbitraryValOption::I32(v) => {
1141                    let v: Option<i32> = v.into_val(env);
1142                    v.into_val(env)
1143                }
1144                ArbitraryValOption::U64(v) => {
1145                    let v: Option<u64> = v.into_val(env);
1146                    v.into_val(env)
1147                }
1148                ArbitraryValOption::I64(v) => {
1149                    let v: Option<i64> = v.into_val(env);
1150                    v.into_val(env)
1151                }
1152                ArbitraryValOption::U128(v) => {
1153                    let v: Option<u128> = v.into_val(env);
1154                    v.into_val(env)
1155                }
1156                ArbitraryValOption::I128(v) => {
1157                    let v: Option<i128> = v.into_val(env);
1158                    v.into_val(env)
1159                }
1160                ArbitraryValOption::U256(v) => {
1161                    let v: Option<U256> = v.into_val(env);
1162                    v.into_val(env)
1163                }
1164                ArbitraryValOption::I256(v) => {
1165                    let v: Option<I256> = v.into_val(env);
1166                    v.into_val(env)
1167                }
1168                ArbitraryValOption::Bytes(v) => {
1169                    let v: Option<Bytes> = v.into_val(env);
1170                    v.into_val(env)
1171                }
1172                ArbitraryValOption::BytesN(v) => {
1173                    let v: Option<BytesN<32>> = v.into_val(env);
1174                    v.into_val(env)
1175                }
1176                ArbitraryValOption::String(v) => {
1177                    let v: Option<String> = v.into_val(env);
1178                    v.into_val(env)
1179                }
1180                ArbitraryValOption::Symbol(v) => {
1181                    let v: Option<Symbol> = v.into_val(env);
1182                    v.into_val(env)
1183                }
1184                ArbitraryValOption::Vec(v) => {
1185                    let v: Option<Vec<u32>> = v.into_val(env);
1186                    v.into_val(env)
1187                }
1188                ArbitraryValOption::Map(v) => {
1189                    let v: Option<Map<u32, u32>> = v.into_val(env);
1190                    v.into_val(env)
1191                }
1192                ArbitraryValOption::Address(v) => {
1193                    let v: Option<Address> = v.into_val(env);
1194                    v.into_val(env)
1195                }
1196                ArbitraryValOption::Timepoint(v) => {
1197                    let v: Option<Timepoint> = v.into_val(env);
1198                    v.into_val(env)
1199                }
1200                ArbitraryValOption::Duration(v) => {
1201                    let v: Option<Duration> = v.into_val(env);
1202                    v.into_val(env)
1203                }
1204                ArbitraryValOption::Val(v) => {
1205                    let v: Option<Val> = (**v).into_val(env);
1206                    v.into_val(env)
1207                }
1208            })
1209        }
1210    }
1211}
1212
1213/// Additional tools for writing fuzz tests.
1214mod fuzz_test_helpers {
1215    use soroban_env_host::testutils::call_with_suppressed_panic_hook;
1216
1217    /// Catch panics within a fuzz test.
1218    ///
1219    /// The `cargo-fuzz` test harness turns panics into test failures,
1220    /// immediately aborting the process.
1221    ///
1222    /// This function catches panics while temporarily disabling the
1223    /// `cargo-fuzz` panic handler.
1224    ///
1225    /// # Example
1226    ///
1227    /// ```
1228    /// # macro_rules! fuzz_target {
1229    /// #     (|$data:ident: $dty: ty| $body:block) => { };
1230    /// # }
1231    /// # struct ExampleContract;
1232    /// # impl ExampleContract {
1233    /// #   fn new(e: &soroban_sdk::Env, b: &soroban_sdk::BytesN<32>) { }
1234    /// #   fn deposit(&self, a: soroban_sdk::Address, n: i128) { }
1235    /// # }
1236    /// use soroban_sdk::{Address, Env};
1237    /// use soroban_sdk::testutils::arbitrary::{Arbitrary, SorobanArbitrary};
1238    ///
1239    /// #[derive(Arbitrary, Debug)]
1240    /// struct FuzzDeposit {
1241    ///     deposit_amount: i128,
1242    ///     deposit_address: <Address as SorobanArbitrary>::Prototype,
1243    /// }
1244    ///
1245    /// fuzz_target!(|input: FuzzDeposit| {
1246    ///     let env = Env::default();
1247    ///
1248    ///     let contract = ExampleContract::new(env, &env.register_contract(None, ExampleContract {}));
1249    ///
1250    ///     let addresses: Address = input.deposit_address.into_val(&env);
1251    ///     let r = contract.try_deposit(deposit_address, input.deposit_amount);
1252    /// });
1253    /// ```
1254    #[deprecated(note = "use [Env::try_invoke] or the try_ functions on a contract client")]
1255    pub fn fuzz_catch_panic<F, R>(f: F) -> std::thread::Result<R>
1256    where
1257        F: FnOnce() -> R,
1258    {
1259        call_with_suppressed_panic_hook(std::panic::AssertUnwindSafe(f))
1260    }
1261}
1262
1263#[cfg(test)]
1264mod tests {
1265    use super::*;
1266    use crate::{
1267        Address, Bytes, BytesN, Duration, Error, Map, String, Symbol, Timepoint, Val, Vec, I256,
1268        U256,
1269    };
1270    use crate::{Env, IntoVal};
1271    use arbitrary::{Arbitrary, Unstructured};
1272    use rand::{RngCore, SeedableRng};
1273
1274    fn run_test<T>()
1275    where
1276        T: SorobanArbitrary,
1277        T::Prototype: for<'a> Arbitrary<'a>,
1278    {
1279        let env = Env::default();
1280        let mut rng = rand::rngs::StdRng::seed_from_u64(0);
1281        let mut rng_data = [0u8; 64];
1282
1283        for _ in 0..100 {
1284            rng.fill_bytes(&mut rng_data);
1285            let mut unstructured = Unstructured::new(&rng_data);
1286            loop {
1287                match T::Prototype::arbitrary(&mut unstructured) {
1288                    Ok(input) => {
1289                        let _val: T = input.into_val(&env);
1290                        break;
1291                    }
1292                    Err(_) => {}
1293                }
1294            }
1295        }
1296    }
1297
1298    #[test]
1299    fn test_unit() {
1300        run_test::<()>()
1301    }
1302
1303    #[test]
1304    fn test_bool() {
1305        run_test::<bool>()
1306    }
1307
1308    #[test]
1309    fn test_u32() {
1310        run_test::<u32>()
1311    }
1312
1313    #[test]
1314    fn test_i32() {
1315        run_test::<i32>()
1316    }
1317
1318    #[test]
1319    fn test_u64() {
1320        run_test::<u64>()
1321    }
1322
1323    #[test]
1324    fn test_i64() {
1325        run_test::<i64>()
1326    }
1327
1328    #[test]
1329    fn test_u128() {
1330        run_test::<u128>()
1331    }
1332
1333    #[test]
1334    fn test_i128() {
1335        run_test::<i128>()
1336    }
1337
1338    #[test]
1339    fn test_u256() {
1340        run_test::<U256>()
1341    }
1342
1343    #[test]
1344    fn test_i256() {
1345        run_test::<I256>()
1346    }
1347
1348    #[test]
1349    fn test_bytes() {
1350        run_test::<Bytes>()
1351    }
1352
1353    #[test]
1354    fn test_string() {
1355        run_test::<String>()
1356    }
1357
1358    #[test]
1359    fn test_bytes_n() {
1360        run_test::<BytesN<32>>()
1361    }
1362
1363    #[test]
1364    fn test_symbol() {
1365        run_test::<Symbol>()
1366    }
1367
1368    #[test]
1369    fn test_address() {
1370        run_test::<Address>()
1371    }
1372
1373    #[test]
1374    fn test_val() {
1375        run_test::<Val>()
1376    }
1377
1378    #[test]
1379    fn test_vec_void() {
1380        run_test::<Vec<()>>()
1381    }
1382
1383    #[test]
1384    fn test_vec_bool() {
1385        run_test::<Vec<bool>>()
1386    }
1387
1388    #[test]
1389    fn test_vec_error() {
1390        run_test::<Vec<Error>>()
1391    }
1392
1393    #[test]
1394    fn test_vec_u32() {
1395        run_test::<Vec<u32>>()
1396    }
1397
1398    #[test]
1399    fn test_vec_i32() {
1400        run_test::<Vec<i32>>()
1401    }
1402
1403    #[test]
1404    fn test_vec_u64() {
1405        run_test::<Vec<u64>>()
1406    }
1407
1408    #[test]
1409    fn test_vec_i64() {
1410        run_test::<Vec<i64>>()
1411    }
1412
1413    #[test]
1414    fn test_vec_u128() {
1415        run_test::<Vec<u128>>()
1416    }
1417
1418    #[test]
1419    fn test_vec_i128() {
1420        run_test::<Vec<i128>>()
1421    }
1422
1423    #[test]
1424    fn test_vec_u256() {
1425        run_test::<Vec<U256>>()
1426    }
1427
1428    #[test]
1429    fn test_vec_i256() {
1430        run_test::<Vec<I256>>()
1431    }
1432
1433    #[test]
1434    fn test_vec_bytes() {
1435        run_test::<Vec<Bytes>>()
1436    }
1437
1438    #[test]
1439    fn test_vec_bytes_n() {
1440        run_test::<Vec<BytesN<32>>>()
1441    }
1442
1443    #[test]
1444    fn test_vec_string() {
1445        run_test::<Vec<String>>()
1446    }
1447
1448    #[test]
1449    fn test_vec_symbol() {
1450        run_test::<Vec<Symbol>>()
1451    }
1452
1453    #[test]
1454    fn test_vec_vec_u32() {
1455        run_test::<Vec<Vec<u32>>>()
1456    }
1457
1458    #[test]
1459    fn test_vec_vec_bytes() {
1460        run_test::<Vec<Vec<Bytes>>>()
1461    }
1462
1463    #[test]
1464    fn test_vec_timepoint() {
1465        run_test::<Vec<Timepoint>>()
1466    }
1467
1468    #[test]
1469    fn test_vec_duration() {
1470        run_test::<Vec<Duration>>()
1471    }
1472
1473    #[test]
1474    fn test_vec_map_u32() {
1475        run_test::<Vec<Map<u32, u32>>>()
1476    }
1477
1478    #[test]
1479    fn test_vec_address() {
1480        run_test::<Vec<Address>>()
1481    }
1482
1483    #[test]
1484    fn test_vec_val() {
1485        run_test::<Vec<Val>>()
1486    }
1487
1488    #[test]
1489    fn test_map_void() {
1490        run_test::<Map<(), ()>>()
1491    }
1492
1493    #[test]
1494    fn test_map_bool() {
1495        run_test::<Map<bool, bool>>()
1496    }
1497
1498    #[test]
1499    fn test_map_error() {
1500        run_test::<Map<Error, Error>>()
1501    }
1502
1503    #[test]
1504    fn test_map_u32() {
1505        run_test::<Map<u32, Vec<u32>>>()
1506    }
1507
1508    #[test]
1509    fn test_map_i32() {
1510        run_test::<Map<i32, Vec<i32>>>()
1511    }
1512
1513    #[test]
1514    fn test_map_u64() {
1515        run_test::<Map<u64, Vec<u64>>>()
1516    }
1517
1518    #[test]
1519    fn test_map_i64() {
1520        run_test::<Map<i64, Vec<i64>>>()
1521    }
1522
1523    #[test]
1524    fn test_map_u128() {
1525        run_test::<Map<u128, Vec<u128>>>()
1526    }
1527
1528    #[test]
1529    fn test_map_i128() {
1530        run_test::<Map<i128, Vec<i128>>>()
1531    }
1532
1533    #[test]
1534    fn test_map_u256() {
1535        run_test::<Map<U256, Vec<U256>>>()
1536    }
1537
1538    #[test]
1539    fn test_map_i256() {
1540        run_test::<Map<I256, Vec<I256>>>()
1541    }
1542
1543    #[test]
1544    fn test_map_bytes() {
1545        run_test::<Map<Bytes, Bytes>>()
1546    }
1547
1548    #[test]
1549    fn test_map_bytes_n() {
1550        run_test::<Map<BytesN<32>, Bytes>>()
1551    }
1552
1553    #[test]
1554    fn test_map_string() {
1555        run_test::<Map<String, String>>()
1556    }
1557
1558    #[test]
1559    fn test_map_symbol() {
1560        run_test::<Map<Symbol, Symbol>>()
1561    }
1562
1563    #[test]
1564    fn test_map_vec_u32() {
1565        run_test::<Map<Vec<u32>, Vec<u32>>>()
1566    }
1567
1568    #[test]
1569    fn test_map_vec_bytes() {
1570        run_test::<Map<Vec<Bytes>, Vec<Bytes>>>()
1571    }
1572
1573    #[test]
1574    fn test_map_timepoint() {
1575        run_test::<Map<Timepoint, Timepoint>>()
1576    }
1577
1578    #[test]
1579    fn test_map_duration() {
1580        run_test::<Map<Duration, Duration>>()
1581    }
1582
1583    fn test_map_map_u32() {
1584        run_test::<Map<Map<u32, u32>, Map<u32, u32>>>()
1585    }
1586
1587    #[test]
1588    fn test_map_address() {
1589        run_test::<Map<Address, Address>>()
1590    }
1591
1592    #[test]
1593    fn test_map_val() {
1594        run_test::<Map<Val, Val>>()
1595    }
1596
1597    #[test]
1598    fn test_timepoint() {
1599        run_test::<Timepoint>()
1600    }
1601
1602    #[test]
1603    fn test_duration() {
1604        run_test::<Duration>()
1605    }
1606
1607    #[test]
1608    fn test_tuples() {
1609        run_test::<(u32,)>();
1610        run_test::<(u32, u32)>();
1611        run_test::<(u32, u32, u32)>();
1612        run_test::<(u32, u32, u32, u32)>();
1613        run_test::<(u32, u32, u32, u32, u32)>();
1614        run_test::<(u32, u32, u32, u32, u32, u32)>();
1615        run_test::<(u32, u32, u32, u32, u32, u32, u32)>();
1616        run_test::<(u32, u32, u32, u32, u32, u32, u32, u32)>();
1617        run_test::<(u32, u32, u32, u32, u32, u32, u32, u32, u32)>();
1618        run_test::<(u32, u32, u32, u32, u32, u32, u32, u32, u32, u32)>();
1619        run_test::<(u32, u32, u32, u32, u32, u32, u32, u32, u32, u32, u32)>();
1620        run_test::<(u32, u32, u32, u32, u32, u32, u32, u32, u32, u32, u32, u32)>();
1621
1622        run_test::<(u32, Address, Vec<Timepoint>, Map<Duration, u64>)>();
1623    }
1624
1625    #[test]
1626    fn test_option() {
1627        run_test::<Option<u32>>();
1628        run_test::<Option<Vec<u32>>>();
1629    }
1630
1631    // Test that sometimes generated vecs have the wrong element types.
1632    #[test]
1633    fn test_vec_wrong_types() {
1634        // These number are tuned for StdRng.
1635        // If StdRng ever changes the test could break.
1636        let iterations = 1000;
1637        let seed = 3;
1638        let acceptable_ratio = 900;
1639
1640        let (mut seen_good, mut seen_bad, mut seen_empty) = (0, 0, 0);
1641
1642        let env = Env::default();
1643        let mut rng = rand::rngs::StdRng::seed_from_u64(seed);
1644        let mut rng_data = [0u8; 64];
1645
1646        for _ in 0..iterations {
1647            rng.fill_bytes(&mut rng_data);
1648            let mut unstructured = Unstructured::new(&rng_data);
1649            let input = <Vec<u32> as SorobanArbitrary>::Prototype::arbitrary(&mut unstructured)
1650                .expect("SorobanArbitrary");
1651            let vec: Vec<u32> = input.into_val(&env);
1652
1653            let has_good_elts = (0..vec.len()).all(|i| vec.try_get(i).is_ok()) && !vec.is_empty();
1654            // Look for elements that cause an error.
1655            let has_bad_elt = (0..vec.len()).any(|i| vec.try_get(i).is_err());
1656
1657            if has_bad_elt {
1658                seen_bad += 1;
1659            } else if has_good_elts {
1660                seen_good += 1;
1661            } else {
1662                seen_empty += 1;
1663            }
1664        }
1665
1666        assert!(seen_good > 0);
1667        assert!(seen_bad > 0);
1668
1669        // sanity check the ratio of good to bad
1670        assert!(seen_good * seen_empty > seen_bad * acceptable_ratio);
1671    }
1672
1673    // Test that sometimes generated maps have the wrong element types.
1674    #[test]
1675    fn test_map_wrong_types() {
1676        // These number are tuned for StdRng.
1677        // If StdRng ever changes the test could break.
1678        let iterations = 4000;
1679        let seed = 13;
1680        let acceptable_ratio = 900;
1681
1682        let (mut seen_good, mut seen_bad_key, mut seen_bad_value, mut seen_empty) = (0, 0, 0, 0);
1683
1684        let env = Env::default();
1685        let mut rng = rand::rngs::StdRng::seed_from_u64(seed);
1686        let mut rng_data = [0u8; 128];
1687
1688        for _ in 0..iterations {
1689            rng.fill_bytes(&mut rng_data);
1690            let mut unstructured = Unstructured::new(&rng_data);
1691            let input =
1692                <Map<u32, u32> as SorobanArbitrary>::Prototype::arbitrary(&mut unstructured)
1693                    .expect("SorobanArbitrary");
1694            let map: Map<u32, u32> = input.into_val(&env);
1695
1696            // Look for elements that cause an error.
1697            let keys = map.keys();
1698            let values = map.values();
1699
1700            let has_good_keys =
1701                (0..keys.len()).all(|i| keys.try_get(i).is_ok()) && !keys.is_empty();
1702            let has_good_values =
1703                (0..values.len()).all(|i| values.try_get(i).is_ok()) && !keys.is_empty();
1704            let has_bad_key = (0..keys.len()).any(|i| keys.try_get(i).is_err());
1705            let has_bad_value = (0..values.len()).any(|i| values.try_get(i).is_err());
1706
1707            if has_bad_key {
1708                seen_bad_key += 1;
1709            } else if has_bad_value {
1710                seen_bad_value += 1;
1711            } else if has_good_keys && has_good_values {
1712                seen_good += 1;
1713            } else {
1714                seen_empty += 1;
1715            }
1716        }
1717
1718        assert!(seen_good > 0);
1719        assert!(seen_bad_key > 0);
1720        assert!(seen_bad_value > 0);
1721
1722        // sanity check the ratio of good to bad
1723        assert!(seen_good * seen_empty > (seen_bad_key + seen_bad_value) * acceptable_ratio);
1724    }
1725
1726    mod user_defined_types {
1727        use super::run_test;
1728        use crate as soroban_sdk;
1729        use crate::{
1730            Address, Bytes, BytesN, Duration, Error, Map, Symbol, Timepoint, Vec, I256, U256,
1731        };
1732        use soroban_sdk::contracttype;
1733
1734        #[contracttype]
1735        #[derive(Clone, Debug, Eq, PartialEq)]
1736        struct PrivStruct {
1737            count_u: u32,
1738            count_i: i32,
1739            bytes_n: BytesN<32>,
1740            vec: Vec<Bytes>,
1741            map: Map<Bytes, Vec<i32>>,
1742            u256: U256,
1743            i156: I256,
1744            error: Error,
1745            address: Address,
1746            symbol: Symbol,
1747            duration: Duration,
1748            timepoint: Timepoint,
1749            nil: (),
1750            vec_tuple: Vec<(u32, Address)>,
1751            option: Option<u32>,
1752        }
1753
1754        #[test]
1755        fn test_user_defined_priv_struct() {
1756            run_test::<PrivStruct>();
1757        }
1758
1759        #[test]
1760        fn test_option_user_defined_priv_struct() {
1761            run_test::<Option<PrivStruct>>();
1762        }
1763
1764        #[contracttype]
1765        #[derive(Clone, Debug, Eq, PartialEq)]
1766        struct PrivStructPubFields {
1767            pub count_u: u32,
1768            pub count_i: i32,
1769            pub bytes_n: BytesN<32>,
1770            pub vec: Vec<Bytes>,
1771            pub map: Map<Bytes, Vec<i32>>,
1772        }
1773
1774        #[test]
1775        fn test_user_defined_priv_struct_pub_fields() {
1776            run_test::<PrivStructPubFields>();
1777        }
1778
1779        #[contracttype]
1780        #[derive(Clone, Debug, Eq, PartialEq)]
1781        pub struct PubStruct {
1782            count_u: u32,
1783            count_i: i32,
1784            bytes_n: BytesN<32>,
1785            vec: Vec<Bytes>,
1786            map: Map<Bytes, Vec<i32>>,
1787        }
1788
1789        #[test]
1790        fn test_user_defined_pub_struct() {
1791            run_test::<PubStruct>();
1792        }
1793
1794        #[contracttype]
1795        #[derive(Clone, Debug, Eq, PartialEq)]
1796        pub struct PubStructPubFields {
1797            pub count_u: u32,
1798            pub count_i: i32,
1799            pub bytes_n: BytesN<32>,
1800            pub vec: Vec<Bytes>,
1801            pub map: Map<Bytes, Vec<i32>>,
1802        }
1803
1804        #[test]
1805        fn test_user_defined_pubstruct_pub_fields() {
1806            run_test::<PubStructPubFields>();
1807        }
1808
1809        #[contracttype]
1810        #[derive(Clone, Debug, Eq, PartialEq)]
1811        struct PrivTupleStruct(
1812            u32,
1813            i32,
1814            BytesN<32>,
1815            Vec<Bytes>,
1816            Map<Bytes, Vec<i32>>,
1817            Vec<(u32, Address)>,
1818            Option<u32>,
1819        );
1820
1821        #[test]
1822        fn test_user_defined_priv_tuple_struct() {
1823            run_test::<PrivTupleStruct>();
1824        }
1825
1826        #[test]
1827        fn test_option_user_defined_priv_tuple_struct() {
1828            run_test::<Option<PrivTupleStruct>>();
1829        }
1830
1831        #[contracttype]
1832        #[derive(Clone, Debug, Eq, PartialEq)]
1833        struct PrivTupleStructPubFields(
1834            pub u32,
1835            pub i32,
1836            pub BytesN<32>,
1837            pub Vec<Bytes>,
1838            pub Map<Bytes, Vec<i32>>,
1839            pub Vec<(u32, Address)>,
1840        );
1841
1842        #[test]
1843        fn test_user_defined_priv_tuple_struct_pub_fields() {
1844            run_test::<PrivTupleStructPubFields>();
1845        }
1846
1847        #[contracttype]
1848        #[derive(Clone, Debug, Eq, PartialEq)]
1849        pub struct PubTupleStruct(u32, i32, BytesN<32>, Vec<Bytes>, Map<Bytes, Vec<i32>>);
1850
1851        #[test]
1852        fn test_user_defined_pub_tuple_struct() {
1853            run_test::<PubTupleStruct>();
1854        }
1855
1856        #[contracttype]
1857        #[derive(Clone, Debug, Eq, PartialEq)]
1858        pub struct PubTupleStructPubFields(
1859            pub u32,
1860            pub i32,
1861            pub BytesN<32>,
1862            pub Vec<Bytes>,
1863            pub Map<Bytes, Vec<i32>>,
1864            pub Vec<(u32, Address)>,
1865        );
1866
1867        #[test]
1868        fn test_user_defined_pub_tuple_struct_pub_fields() {
1869            run_test::<PubTupleStructPubFields>();
1870        }
1871
1872        #[contracttype]
1873        #[derive(Clone, Debug, Eq, PartialEq)]
1874        pub(crate) struct PubCrateStruct(u32);
1875
1876        #[test]
1877        fn test_user_defined_pub_crate_struct() {
1878            run_test::<PubCrateStruct>();
1879        }
1880
1881        #[contracttype]
1882        #[derive(Clone, Debug, Eq, PartialEq)]
1883        enum PrivEnum {
1884            A(u32),
1885            Aa(u32, u32),
1886            C,
1887            D,
1888            E(Vec<(u32, Address)>),
1889            F(Option<u32>),
1890        }
1891
1892        #[test]
1893        fn test_user_defined_priv_enum() {
1894            run_test::<PrivEnum>();
1895        }
1896
1897        #[test]
1898        fn test_option_user_defined_priv_enum() {
1899            run_test::<Option<PrivEnum>>();
1900        }
1901
1902        #[contracttype]
1903        #[derive(Clone, Debug, Eq, PartialEq)]
1904        pub enum PubEnum {
1905            A(u32),
1906            C,
1907            D,
1908        }
1909
1910        #[test]
1911        fn test_user_defined_pub_enum() {
1912            run_test::<PubEnum>();
1913        }
1914
1915        #[contracttype]
1916        #[derive(Clone, Debug, Eq, PartialEq)]
1917        pub(crate) enum PubCrateEnum {
1918            A(u32),
1919            C,
1920            D,
1921        }
1922
1923        #[test]
1924        fn test_user_defined_pub_crate_enum() {
1925            run_test::<PubCrateEnum>();
1926        }
1927
1928        #[contracttype]
1929        #[derive(Copy, Clone, Debug, Eq, PartialEq)]
1930        enum PrivEnumInt {
1931            A = 1,
1932            C = 2,
1933            D = 3,
1934        }
1935
1936        #[test]
1937        fn test_user_defined_priv_enum_int() {
1938            run_test::<PrivEnumInt>();
1939        }
1940
1941        #[contracttype]
1942        #[derive(Copy, Clone, Debug, Eq, PartialEq)]
1943        pub enum PubEnumInt {
1944            A = 1,
1945            C = 2,
1946            D = 3,
1947        }
1948
1949        #[test]
1950        fn test_user_defined_pub_enum_int() {
1951            run_test::<PubEnumInt>();
1952        }
1953
1954        #[test]
1955        fn test_declared_inside_a_fn() {
1956            #[contracttype]
1957            struct Foo {
1958                a: u32,
1959            }
1960
1961            #[contracttype]
1962            enum Bar {
1963                Baz,
1964                Qux,
1965            }
1966
1967            run_test::<Foo>();
1968            run_test::<Bar>();
1969        }
1970
1971        fn test_structs_and_enums_inside_tuples() {
1972            #[contracttype]
1973            struct Foo(u32);
1974
1975            #[contracttype]
1976            enum Bar {
1977                Baz,
1978            }
1979
1980            run_test::<(Foo, Bar)>();
1981        }
1982    }
1983}