Skip to main content

soroban_sdk/
lib.rs

1//! Soroban SDK supports writing smart contracts for the Wasm-powered [Soroban] smart contract
2//! runtime, deployed on [Stellar].
3//!
4//! ### Docs
5//!
6//! See [developers.stellar.org] for documentation about building smart contracts for [Stellar].
7//!
8//! [developers.stellar.org]: https://developers.stellar.org
9//! [Stellar]: https://stellar.org
10//! [Soroban]: https://stellar.org/soroban
11//!
12//! ### Support
13//!
14//! The two most recent soroban-sdk major releases are supported with critical security fixes.
15//! Critical security issues may be backported to earlier versions if practical, but not guaranteed.
16//! General bugs are only fixed on, and new features are only added to, the latest major release.
17//!
18//! ### Build Target
19//!
20//! Contracts must be built for the `wasm32v1-none` target, available with Rust 1.84+. It is the
21//! only wasm target supported by the Soroban runtime on Stellar.
22//!
23//! Build contracts with `stellar contract build` from [stellar-cli], which targets `wasm32v1-none`
24//! and applies the build settings the Soroban runtime requires. Do not build contracts with
25//! `cargo build`. As of soroban-sdk v28, [stellar-cli] v25.2.0 or newer is required.
26//!
27//! The `wasm32-unknown-unknown` target is not supported when building with Rust 1.82 or newer,
28//! because on those versions the target enables wasm features (reference-types, multi-value) that
29//! the Soroban environment does not support and that cannot be easily disabled. Building for
30//! `wasm32-unknown-unknown` on Rust 1.82+ produces a build error.
31//!
32//! [stellar-cli]: https://github.com/stellar/stellar-cli
33//!
34//! ### Features
35//!
36//! See [_features] for a list of all Cargo features and what they do.
37//!
38//! ### Migrating Major Versions
39//!
40//! See [_migrating] for a summary of how to migrate from one major version to another.
41//!
42//! ### Examples
43//!
44//! ```rust
45//! use soroban_sdk::{contract, contractevent, contractimpl, symbol_short, Address, Env};
46//!
47//! #[contract]
48//! pub struct Contract;
49//!
50//! #[contractevent]
51//! pub struct Hello {
52//!     pub to: Address,
53//! }
54//!
55//! #[contractimpl]
56//! impl Contract {
57//!     pub fn __constructor(env: &Env, owner: Address) {
58//!         env.storage().instance().set(&symbol_short!("owner"), &owner);
59//!     }
60//!
61//!     pub fn owner(env: &Env) -> Address {
62//!         env.storage().instance()
63//!             .get(&symbol_short!("owner"))
64//!             .unwrap()
65//!     }
66//!
67//!     pub fn hello(env: &Env, to: Address) {
68//!         Self::owner(env).require_auth();
69//!         Hello { to }.publish(env);
70//!     }
71//! }
72//!
73//! #[test]
74//! fn test() {
75//! # }
76//! # #[cfg(feature = "testutils")]
77//! # fn main() {
78//!     use soroban_sdk::{
79//!         testutils::{Address as _, AuthorizedFunction, AuthorizedInvocation, Events as _},
80//!         Event as _, IntoVal,
81//!     };
82//!
83//!     let env = Env::default();
84//!     let owner = Address::generate(&env);
85//!     let contract_id = env.register(Contract, (&owner,));
86//!     let client = ContractClient::new(&env, &contract_id);
87//!
88//!     let to = Address::generate(&env);
89//!
90//!     client.mock_all_auths().hello(&to);
91//!
92//!     assert_eq!(
93//!         env.auths(),
94//!         [
95//!             (owner, AuthorizedInvocation { function: AuthorizedFunction::Contract((contract_id.clone(), symbol_short!("hello"), (&to,).into_val(&env))), sub_invocations: [].into() }),
96//!         ],
97//!     );
98//!
99//!     assert_eq!(
100//!         env.events().all(),
101//!         [
102//!             Hello { to }.to_xdr(&env, &contract_id),
103//!         ],
104//!     );
105//! }
106//! # #[cfg(not(feature = "testutils"))]
107//! # fn main() { }
108//! ```
109//!
110//! More examples are available at:
111//! - <https://developers.stellar.org/docs/build/smart-contracts/example-contracts>
112//! - <https://developers.stellar.org/docs/build/guides>
113
114#![cfg_attr(target_family = "wasm", no_std)]
115#![cfg_attr(feature = "docs", feature(doc_cfg))]
116#![allow(dead_code)]
117
118pub mod _features;
119pub mod _migrating;
120
121#[cfg(all(target_family = "wasm", feature = "testutils"))]
122compile_error!("'testutils' feature is not supported on 'wasm' target");
123
124// When used in a no_std contract, provide a panic handler as one is required.
125#[cfg(target_family = "wasm")]
126#[panic_handler]
127fn handle_panic(_: &core::panic::PanicInfo) -> ! {
128    core::arch::wasm32::unreachable()
129}
130
131#[cfg(feature = "alloc")]
132#[cfg_attr(feature = "docs", doc(cfg(feature = "alloc")))]
133pub mod alloc;
134
135/// This const block contains link sections that need to end up in the final
136/// build of any contract using the SDK.
137///
138/// In Rust's build system sections only get included into the final build if
139/// the object file containing those sections are processed by the linker, but
140/// as an optimization step if no code is called in an object file it is
141/// discarded.  This has the unfortunate effect of causing anything else in
142/// those object files, such as link sections, to be discarded. Placing anything
143/// that must be included in the build inside an exported static or function
144/// ensures the object files won't be discarded. wasm-bindgen does a similar
145/// thing to this with a function, and so this seems to be a reasonably
146/// accepted way to work around this limitation in the build system. The SDK
147/// uses a static exported with name `_` that becomes a global because a global
148/// is more unnoticeable, and takes up less bytes.
149///
150/// The const block has no affect on the above problem and exists only to group
151/// the static and link sections under a shared cfg.
152///
153/// See https://github.com/stellar/rs-soroban-sdk/issues/383 for more details.
154#[cfg(target_family = "wasm")]
155const _: () = {
156    /// This exported static is guaranteed to end up in the final binary of any
157    /// importer, as a global. It exists to ensure the link sections are
158    /// included in the final build artifact. See notes above.
159    #[export_name = "_"]
160    static __: () = ();
161
162    #[link_section = "contractenvmetav0"]
163    static __ENV_META_XDR: [u8; env::internal::meta::XDR.len()] = env::internal::meta::XDR;
164
165    // Rustc version.
166    contractmeta!(key = "rsver", val = env!("RUSTC_VERSION"),);
167
168    // Rust Soroban SDK version. Don't emit when the cfg is set. The cfg is set when building test
169    // wasms in this repository, so that every commit in this repo does not cause the test wasms in
170    // this repo to have a new hash due to the revision being embedded. The wasm hash gets embedded
171    // into a few places, such as test snapshots, or get used in test themselves where if they are
172    // constantly changing creates repetitive diffs.
173    #[cfg(not(soroban_sdk_internal_no_rssdkver_meta))]
174    contractmeta!(
175        key = "rssdkver",
176        val = concat!(env!("CARGO_PKG_VERSION"), "#", env!("GIT_REVISION")),
177    );
178
179    // An indicator of the spec shaking version in use. Signals to the stellar-cli that the .wasm
180    // needs to have its spec shaken. See soroban_spec::shaking for constants and version detection.
181    // The contractmeta! macro requires string literals, so we assert the literals match the
182    // constants defined in soroban_spec::shaking.
183    contractmeta!(key = "rssdk_spec_shaking", val = "2");
184};
185
186// Re-exports of dependencies used by macros.
187#[doc(hidden)]
188pub mod reexports_for_macros {
189    pub use bytes_lit;
190    #[cfg(any(test, feature = "testutils"))]
191    pub use ctor;
192}
193
194/// `debug_assert_in_contract!` asserts that the contract is currently executing within a
195/// contract. The macro expands to an assertion when testutils are enabled or in tests,
196/// otherwise it expands to nothing.
197macro_rules! debug_assert_in_contract {
198    ($env:expr $(,)?) => {{
199        {
200            #[cfg(any(test, feature = "testutils"))]
201            assert!(
202                ($env).in_contract(),
203                "this function is not accessible outside of a contract, wrap \
204                the call with `env.as_contract()` to access it from a \
205                particular contract"
206            );
207        }
208    }};
209}
210
211// For internal use, use `debug_assert_in_contract!` instead.
212/// Assert in contract asserts that the contract is currently executing within a
213/// contract. The macro maps to code when testutils are enabled or in tests,
214/// otherwise maps to nothing.
215#[deprecated(note = "this macro is deprecated and will be removed in a future release")]
216#[macro_export]
217macro_rules! assert_in_contract {
218    ($env:expr $(,)?) => {{
219        {
220            #[cfg(any(test, feature = "testutils"))]
221            assert!(
222                ($env).in_contract(),
223                "this function is not accessible outside of a contract, wrap \
224                the call with `env.as_contract()` to access it from a \
225                particular contract"
226            );
227        }
228    }};
229}
230
231/// Create a short [Symbol] constant with the given string.
232///
233/// A short symbol's maximum length is 9 characters. For longer symbols, use
234/// [Symbol::new] to create the symbol at runtime.
235///
236/// Valid characters are `a-zA-Z0-9_`.
237///
238/// The [Symbol] is generated at compile time and returned as a const.
239///
240/// ### Examples
241///
242/// ```
243/// use soroban_sdk::{symbol_short, Symbol};
244///
245/// let symbol = symbol_short!("a_str");
246/// assert_eq!(symbol, symbol_short!("a_str"));
247/// ```
248pub use soroban_sdk_macros::symbol_short;
249
250/// Generates conversions from the repr(u32) enum from/into an `Error`.
251///
252/// There are some constraints on the types that are supported:
253/// - Enum must derive `Copy`.
254/// - Enum variants must have an explicit integer literal.
255/// - Enum variants must have a value convertible to u32.
256///
257/// Includes the type in the contract spec so that clients can generate bindings
258/// for the type.
259///
260/// ### Examples
261///
262/// Defining an error and capturing errors using the `try_` variant.
263///
264/// ```
265/// use soroban_sdk::{contract, contracterror, contractimpl, Env};
266///
267/// #[contracterror]
268/// #[derive(Copy, Clone, Debug, Eq, PartialEq, PartialOrd, Ord)]
269/// #[repr(u32)]
270/// pub enum Error {
271///     MyError = 1,
272///     AnotherError = 2,
273/// }
274///
275/// #[contract]
276/// pub struct Contract;
277///
278/// #[contractimpl]
279/// impl Contract {
280///     pub fn causeerror(env: Env) -> Result<(), Error> {
281///         Err(Error::MyError)
282///     }
283/// }
284///
285/// #[test]
286/// fn test() {
287/// # }
288/// # #[cfg(feature = "testutils")]
289/// # fn main() {
290///     let env = Env::default();
291///
292///     // Register the contract defined in this crate.
293///     let contract_id = env.register(Contract, ());
294///
295///     // Create a client for calling the contract.
296///     let client = ContractClient::new(&env, &contract_id);
297///
298///     // Invoke contract causeerror function, but use the try_ variant that
299///     // will capture the error so we can inspect.
300///     let result = client.try_causeerror();
301///     assert_eq!(result, Err(Ok(Error::MyError)));
302/// }
303/// # #[cfg(not(feature = "testutils"))]
304/// # fn main() { }
305/// ```
306///
307/// Testing invocations that cause errors with `should_panic` instead of `try_`.
308///
309/// ```should_panic
310/// # use soroban_sdk::{contract, contracterror, contractimpl, Env};
311/// #
312/// # #[contracterror]
313/// # #[derive(Copy, Clone, Debug, Eq, PartialEq, PartialOrd, Ord)]
314/// # #[repr(u32)]
315/// # pub enum Error {
316/// #     MyError = 1,
317/// #     AnotherError = 2,
318/// # }
319/// #
320/// # #[contract]
321/// # pub struct Contract;
322/// #
323/// # #[contractimpl]
324/// # impl Contract {
325/// #     pub fn causeerror(env: Env) -> Result<(), Error> {
326/// #         Err(Error::MyError)
327/// #     }
328/// # }
329/// #
330/// #[test]
331/// #[should_panic(expected = "ContractError(1)")]
332/// fn test() {
333/// # panic!("ContractError(1)");
334/// # }
335/// # #[cfg(feature = "testutils")]
336/// # fn main() {
337///     let env = Env::default();
338///
339///     // Register the contract defined in this crate.
340///     let contract_id = env.register(Contract, ());
341///
342///     // Create a client for calling the contract.
343///     let client = ContractClient::new(&env, &contract_id);
344///
345///     // Invoke contract causeerror function.
346///     client.causeerror();
347/// }
348/// # #[cfg(not(feature = "testutils"))]
349/// # fn main() { }
350/// ```
351pub use soroban_sdk_macros::contracterror;
352
353/// Import a contract from its WASM file, generating a client, types, and
354/// constant holding the contract file.
355///
356/// The path given is relative to the workspace root, and not the current
357/// file.
358///
359/// Generates in the current module:
360/// - A `Contract` trait that matches the contracts interface.
361/// - A `Client` struct that has functions for each function in the
362/// contract.
363/// - Types for all contract types defined in the contract.
364///
365/// ### SHA-256 Verification
366///
367/// An optional `sha256` parameter can be provided to verify the integrity of
368/// the WASM file at compile time. When provided, the macro computes the
369/// SHA-256 hash of the WASM file at compile time and produces a compile error
370/// if it does not match the provided value. The `sha256` argument must
371/// be a hex-encoded SHA-256 digest (64 hex chars, no 0x prefix).
372///
373/// ```
374/// mod contract_a {
375///     soroban_sdk::contractimport!(
376///         file = "doctest_fixtures/contract.wasm",
377///         sha256 = "33d12fec8f6f3ddf2eb0ec76ee9a75a9e37d1fa20af35908d90d278af8264311",
378///     );
379/// }
380/// ```
381///
382/// ### Examples
383///
384/// ```
385/// use soroban_sdk::{contract, contractimpl, Address, Env};
386///
387/// mod contract_a {
388///     soroban_sdk::contractimport!(file = "doctest_fixtures/contract.wasm");
389/// }
390///
391/// #[contract]
392/// pub struct ContractB;
393///
394/// #[contractimpl]
395/// impl ContractB {
396///     pub fn add_with(env: &Env, contract_id: Address, x: u64, y: u64) -> u64 {
397///         let client = contract_a::Client::new(env, &contract_id);
398///         client.add(&x, &y)
399///     }
400/// }
401///
402/// #[test]
403/// fn test() {
404/// # }
405/// # fn main() {
406///     let env = Env::default();
407///
408///     // Register contract A using the imported WASM.
409///     let contract_a_id = env.register(contract_a::WASM, ());
410///
411///     // Register contract B defined in this crate.
412///     let contract_b_id = env.register(ContractB, ());
413///
414///     // Create a client for calling contract B.
415///     let client = ContractBClient::new(&env, &contract_b_id);
416///
417///     // Invoke contract B via its client.
418///     let sum = client.add_with(&contract_a_id, &5, &7);
419///     assert_eq!(sum, 12);
420/// }
421/// ```
422pub use soroban_sdk_macros::contractimport;
423
424/// Marks a type as being the type that contract functions are attached for.
425///
426/// Use `#[contractimpl]` on impl blocks of this type to make those functions
427/// contract functions.
428///
429/// Note that a crate only ever exports a single contract. While there can be
430/// multiple types in a crate with `#[contract]`, when built as a wasm file and
431/// deployed the combination of all contract functions and all contracts within
432/// a crate will be seen as a single contract.
433///
434/// ### Examples
435///
436/// Define a contract with one function, `hello`, and call it from within a test
437/// using the generated client.
438///
439/// ```
440/// use soroban_sdk::{contract, contractimpl, vec, symbol_short, BytesN, Env, Symbol, Vec};
441///
442/// #[contract]
443/// pub struct HelloContract;
444///
445/// #[contractimpl]
446/// impl HelloContract {
447///     pub fn hello(env: Env, to: Symbol) -> Vec<Symbol> {
448///         vec![&env, symbol_short!("Hello"), to]
449///     }
450/// }
451///
452/// #[test]
453/// fn test() {
454/// # }
455/// # #[cfg(feature = "testutils")]
456/// # fn main() {
457///     let env = Env::default();
458///     let contract_id = env.register(HelloContract, ());
459///     let client = HelloContractClient::new(&env, &contract_id);
460///
461///     let words = client.hello(&symbol_short!("Dev"));
462///
463///     assert_eq!(words, vec![&env, symbol_short!("Hello"), symbol_short!("Dev"),]);
464/// }
465/// # #[cfg(not(feature = "testutils"))]
466/// # fn main() { }
467/// ```
468pub use soroban_sdk_macros::contract;
469
470/// Exports the publicly accessible functions to the Soroban environment.
471///
472/// Functions that are publicly accessible in the implementation are invocable
473/// by other contracts, or directly by transactions, when deployed.
474///
475/// ### Notes
476///
477/// Each public function's export name is derived from the function name alone,
478/// without any type prefix or namespace. This means:
479///
480/// - **Function names must be unique across all `#[contractimpl]` blocks in a
481///   crate.** If two impl blocks define a function with the same name, their
482///   Wasm exports will collide, producing build or linker errors.
483///
484/// - **Importing a crate that contains `#[contractimpl]` blocks will pull its
485///   exported functions into the importing crate's Wasm binary.** This is a
486///   limitation of Rust — any `#[export_name = "..."]` function in a dependency
487///   is included in the final binary. This can cause unexpected exports or name
488///   collisions that are hard to diagnose. For this reason it is usually
489///   inadvisable to import dependencies that use `#[contractimpl]`.
490///
491/// ### Examples
492///
493/// Define a contract with one function, `hello`, and call it from within a test
494/// using the generated client.
495///
496/// ```
497/// use soroban_sdk::{contract, contractimpl, vec, symbol_short, BytesN, Env, Symbol, Vec};
498///
499/// #[contract]
500/// pub struct HelloContract;
501///
502/// #[contractimpl]
503/// impl HelloContract {
504///     pub fn hello(env: Env, to: Symbol) -> Vec<Symbol> {
505///         vec![&env, symbol_short!("Hello"), to]
506///     }
507/// }
508///
509/// #[test]
510/// fn test() {
511/// # }
512/// # #[cfg(feature = "testutils")]
513/// # fn main() {
514///     let env = Env::default();
515///     let contract_id = env.register(HelloContract, ());
516///     let client = HelloContractClient::new(&env, &contract_id);
517///
518///     let words = client.hello(&symbol_short!("Dev"));
519///
520///     assert_eq!(words, vec![&env, symbol_short!("Hello"), symbol_short!("Dev"),]);
521/// }
522/// # #[cfg(not(feature = "testutils"))]
523/// # fn main() { }
524/// ```
525pub use soroban_sdk_macros::contractimpl;
526
527/// Defines a contract trait with default function implementations that can be
528/// used by contracts.
529///
530/// The `contracttrait` macro generates a trait that contracts can implement
531/// using `contractimpl`. Functions defined with default implementations in
532/// the trait will be automatically exported as contract functions when a
533/// contract implements the trait using `#[contractimpl(contracttrait)]`.
534///
535/// This is useful for defining standard interfaces where some functions have
536/// default implementations that can be optionally overridden.
537///
538/// Note: The `contracttrait` macro is not required on traits, but without it
539/// default functions will not be exported by contracts that implement the
540/// trait.
541///
542/// `cfg` and `cfg_attr` attributes are not supported on `#[contracttrait]`
543/// default functions. Direct `cfg` attributes are supported on overriding
544/// methods in `#[contractimpl(contracttrait)]` impls, but `cfg_attr` is not.
545/// Default-function metadata is captured when the trait is defined, but wrappers
546/// for non-overridden defaults are generated later where the trait is
547/// implemented, so carrying cfgs through that handoff could evaluate them in a
548/// different crate's cfg context.
549///
550/// ### Macro Arguments
551///
552/// - `crate_path` - The path to the soroban-sdk crate. Defaults to `soroban_sdk`.
553/// - `spec_name` - The name for the spec type. Defaults to `{TraitName}Spec`.
554/// - `spec_export` - Whether to export the spec for default functions. Defaults to `false`.
555/// - `args_name` - The name for the args type. Defaults to `{TraitName}Args`.
556/// - `client_name` - The name for the client type. Defaults to `{TraitName}Client`.
557///
558/// ### Examples
559///
560/// Define a trait with a default function and implement it in a contract:
561///
562/// ```
563/// use soroban_sdk::{contract, contractimpl, contracttrait, Address, Env};
564///
565/// #[contracttrait]
566/// pub trait Token {
567///     fn balance(env: &Env, id: Address) -> i128 {
568///         // ...
569///         # todo!()
570///     }
571///
572///     // Default function.
573///     fn transfer(env: &Env, from: Address, to: Address, amount: i128) {
574///         // ...
575///         # todo!()
576///     }
577/// }
578///
579/// #[contract]
580/// pub struct TokenContract;
581///
582/// #[contractimpl(contracttrait)]
583/// impl Token for TokenContract {
584///     fn balance(env: &Env, id: Address) -> i128 {
585///         // Provide a custom impl of balance.
586///         // ...
587///         # todo!()
588///     }
589/// }
590/// # fn main() { }
591/// ```
592pub use soroban_sdk_macros::contracttrait;
593
594/// Generates a macro for a trait that calls
595/// contractimpl_trait_default_fns_not_overridden with information about the trait.
596///
597/// This macro is used internally and is not intended to be used directly by contracts.
598#[doc(hidden)]
599pub use soroban_sdk_macros::contractimpl_trait_macro;
600
601/// Generates code the same as contractimpl does, but for the default functions of a trait that are
602/// not overridden.
603///
604/// This macro is used internally and is not intended to be used directly by contracts.
605#[doc(hidden)]
606pub use soroban_sdk_macros::contractimpl_trait_default_fns_not_overridden;
607
608/// Adds a serialized SCMetaEntry::SCMetaV0 to the WASM contracts custom section
609/// under the section name 'contractmetav0'. Contract developers can use this to
610/// append metadata to their contract.
611///
612/// ### Examples
613///
614/// ```
615/// use soroban_sdk::{contract, contractimpl, contractmeta, vec, symbol_short, BytesN, Env, Symbol, Vec};
616///
617/// contractmeta!(key="desc", val="hello world contract");
618///
619/// #[contract]
620/// pub struct HelloContract;
621///
622/// #[contractimpl]
623/// impl HelloContract {
624///     pub fn hello(env: Env, to: Symbol) -> Vec<Symbol> {
625///         vec![&env, symbol_short!("Hello"), to]
626///     }
627/// }
628///
629///
630/// #[test]
631/// fn test() {
632/// # }
633/// # #[cfg(feature = "testutils")]
634/// # fn main() {
635///     let env = Env::default();
636///     let contract_id = env.register(HelloContract, ());
637///     let client = HelloContractClient::new(&env, &contract_id);
638///
639///     let words = client.hello(&symbol_short!("Dev"));
640///
641///     assert_eq!(words, vec![&env, symbol_short!("Hello"), symbol_short!("Dev"),]);
642/// }
643/// # #[cfg(not(feature = "testutils"))]
644/// # fn main() { }
645/// ```
646pub use soroban_sdk_macros::contractmeta;
647
648/// Generates conversions from the struct/enum from/into a `Val`.
649///
650/// There are some constraints on the types that are supported:
651/// - Enums with integer values must have an explicit integer literal for every
652/// variant.
653/// - Enums with unit variants are supported.
654/// - Enums with tuple-like variants with a maximum of one tuple field are
655/// supported. The tuple field must be of a type that is also convertible to and
656/// from `Val`.
657/// - Enums with struct-like variants are not supported.
658/// - Structs are supported. All fields must be of a type that is also
659/// convertible to and from `Val`.
660/// - All variant names, field names, and type names must be 10-characters or
661/// less in length.
662///
663/// Includes the type in the contract spec so that clients can generate bindings
664/// for the type.
665///
666/// ### Examples
667///
668/// Defining a contract type that is a struct and use it in a contract.
669///
670/// ```
671/// #![no_std]
672/// use soroban_sdk::{contract, contractimpl, contracttype, symbol_short, Env, Symbol};
673///
674/// #[contracttype]
675/// #[derive(Clone, Default, Debug, Eq, PartialEq)]
676/// pub struct State {
677///     pub count: u32,
678///     pub last_incr: u32,
679/// }
680///
681/// #[contract]
682/// pub struct Contract;
683///
684/// #[contractimpl]
685/// impl Contract {
686///     /// Increment increments an internal counter, and returns the value.
687///     pub fn increment(env: Env, incr: u32) -> u32 {
688///         // Get the current count.
689///         let mut state = Self::get_state(env.clone());
690///
691///         // Increment the count.
692///         state.count += incr;
693///         state.last_incr = incr;
694///
695///         // Save the count.
696///         env.storage().persistent().set(&symbol_short!("STATE"), &state);
697///
698///         // Return the count to the caller.
699///         state.count
700///     }
701///
702///     /// Return the current state.
703///     pub fn get_state(env: Env) -> State {
704///         env.storage().persistent()
705///             .get(&symbol_short!("STATE"))
706///             .unwrap_or_else(|| State::default()) // If no value set, assume 0.
707///     }
708/// }
709///
710/// #[test]
711/// fn test() {
712/// # }
713/// # #[cfg(feature = "testutils")]
714/// # fn main() {
715///     let env = Env::default();
716///     let contract_id = env.register(Contract, ());
717///     let client = ContractClient::new(&env, &contract_id);
718///
719///     assert_eq!(client.increment(&1), 1);
720///     assert_eq!(client.increment(&10), 11);
721///     assert_eq!(
722///         client.get_state(),
723///         State {
724///             count: 11,
725///             last_incr: 10,
726///         },
727///     );
728/// }
729/// # #[cfg(not(feature = "testutils"))]
730/// # fn main() { }
731/// ```
732///
733/// Defining contract types that are three different types of enums and using
734/// them in a contract.
735///
736/// ```
737/// #![no_std]
738/// use soroban_sdk::{contract, contractimpl, contracttype, symbol_short, Symbol, Env};
739///
740/// /// A tuple enum is stored as a two-element vector containing the name of
741/// /// the enum variant as a Symbol, then the value in the tuple.
742/// #[contracttype]
743/// #[derive(Clone, Debug, Eq, PartialEq)]
744/// pub enum Color {
745///     Red(Intensity),
746///     Blue(Shade),
747/// }
748///
749/// /// A unit enum is stored as a single-element vector containing the name of
750/// /// the enum variant as a Symbol.
751/// #[contracttype]
752/// #[derive(Clone, Debug, Eq, PartialEq)]
753/// pub enum Shade {
754///     Light,
755///     Dark,
756/// }
757///
758/// /// An integer enum is stored as its integer value.
759/// #[contracttype]
760/// #[derive(Copy, Clone, Debug, Eq, PartialEq, PartialOrd, Ord)]
761/// #[repr(u32)]
762/// pub enum Intensity {
763///     Low = 1,
764///     High = 2,
765/// }
766///
767/// #[contract]
768/// pub struct Contract;
769///
770/// #[contractimpl]
771/// impl Contract {
772///     /// Set the color.
773///     pub fn set(env: Env, c: Color) {
774///         env.storage().persistent().set(&symbol_short!("COLOR"), &c);
775///     }
776///
777///     /// Get the color.
778///     pub fn get(env: Env) -> Option<Color> {
779///         env.storage().persistent()
780///             .get(&symbol_short!("COLOR"))
781///     }
782/// }
783///
784/// #[test]
785/// fn test() {
786/// # }
787/// # #[cfg(feature = "testutils")]
788/// # fn main() {
789///     let env = Env::default();
790///     let contract_id = env.register(Contract, ());
791///     let client = ContractClient::new(&env, &contract_id);
792///
793///     assert_eq!(client.get(), None);
794///
795///     client.set(&Color::Red(Intensity::High));
796///     assert_eq!(client.get(), Some(Color::Red(Intensity::High)));
797///
798///     client.set(&Color::Blue(Shade::Light));
799///     assert_eq!(client.get(), Some(Color::Blue(Shade::Light)));
800/// }
801/// # #[cfg(not(feature = "testutils"))]
802/// # fn main() { }
803/// ```
804pub use soroban_sdk_macros::contracttype;
805
806/// Generates conversions from the struct into a published event.
807///
808/// Fields of the struct become topics and data parameters in the published event.
809///
810/// Includes the event in the contract spec so that clients can generate bindings
811/// for the type and downstream systems can understand the meaning of the event.
812///
813/// ### Examples
814///
815/// #### Define an Event
816///
817/// The event will have a single fixed topic matching the name of the struct in lower snake
818/// case. The fixed topic will appear before any topics listed as fields. In the example
819/// below, the topics for the event will be:
820/// - `"my_event"`
821/// - u32 value from the `my_topic` field
822///
823/// The event's data will be a [`Map`], containing a key-value pair for each field with the key
824/// being the name as a [`Symbol`]. A field whose value is void (a `None` [`Option`], or the unit
825/// type `()`) is omitted from the map. Pass `sparse = false` to write every field to the map,
826/// including the fields whose value is void. In the example below, the data for the event will be:
827/// - key: my_event_data => val: u32
828/// - key: more_event_data => val: u64
829///
830/// ```
831/// #![no_std]
832/// use soroban_sdk::contractevent;
833///
834/// // Define the event using the `contractevent` attribute macro.
835/// #[contractevent]
836/// #[derive(Clone, Default, Debug, Eq, PartialEq)]
837/// pub struct MyEvent {
838///     // Mark fields as topics, for the value to be included in the events topic list so
839///     // that downstream systems know to index it.
840///     #[topic]
841///     pub my_topic: u32,
842///     // Fields not marked as topics will appear in the events data section.
843///     pub my_event_data: u32,
844///     pub more_event_data: u64,
845/// }
846///
847/// # fn main() { }
848/// ```
849///
850/// #### Define an Event with Custom Topics
851///
852/// Define a contract event with a custom list of fixed topics.
853///
854/// The fixed topics can be change to another value. In the example
855/// below, the topics for the event will be:
856/// - `"my_contract"`
857/// - `"an_event"`
858/// - u32 value from the `my_topic` field
859///
860/// ```
861/// #![no_std]
862/// use soroban_sdk::contractevent;
863///
864/// // Define the event using the `contractevent` attribute macro.
865/// #[contractevent(topics = ["my_contract", "an_event"])]
866/// #[derive(Clone, Default, Debug, Eq, PartialEq)]
867/// pub struct MyEvent {
868///     // Mark fields as topics, for the value to be included in the events topic list so
869///     // that downstream systems know to index it.
870///     #[topic]
871///     pub my_topic: u32,
872///     // Fields not marked as topics will appear in the events data section.
873///     pub my_event_data: u32,
874///     pub more_event_data: u64,
875/// }
876///
877/// # fn main() { }
878/// ```
879///
880/// #### Define an Event with Other Data Formats
881///
882/// The data format of the event is a map by default, but can alternatively be defined as a `vec`
883/// or `single-value`.
884///
885/// ##### Vec
886///
887/// In the example below, the data for the event will be a [`Vec`] containing:
888/// - u32
889/// - u64
890///
891/// ```
892/// #![no_std]
893/// use soroban_sdk::contractevent;
894///
895/// // Define the event using the `contractevent` attribute macro.
896/// #[contractevent(data_format = "vec")]
897/// #[derive(Clone, Default, Debug, Eq, PartialEq)]
898/// pub struct MyEvent {
899///     // Mark fields as topics, for the value to be included in the events topic list so
900///     // that downstream systems know to index it.
901///     #[topic]
902///     pub my_topic: u32,
903///     // Fields not marked as topics will appear in the events data section.
904///     pub my_event_data: u32,
905///     pub more_event_data: u64,
906/// }
907///
908/// # fn main() { }
909/// ```
910///
911/// ##### Single Value
912///
913/// In the example below, the data for the event will be a u32.
914///
915/// When the data format is a single value there must be no more than one data field.
916///
917/// ```
918/// #![no_std]
919/// use soroban_sdk::contractevent;
920///
921/// // Define the event using the `contractevent` attribute macro.
922/// #[contractevent(data_format = "single-value")]
923/// #[derive(Clone, Default, Debug, Eq, PartialEq)]
924/// pub struct MyEvent {
925///     // Mark fields as topics, for the value to be included in the events topic list so
926///     // that downstream systems know to index it.
927///     #[topic]
928///     pub my_topic: u32,
929///     // Fields not marked as topics will appear in the events data section.
930///     pub my_event_data: u32,
931/// }
932///
933/// # fn main() { }
934/// ```
935///
936/// #### A Full Example
937///
938/// Defining an event, publishing it in a contract, and testing it.
939///
940/// ```
941/// #![no_std]
942/// use soroban_sdk::{contract, contractevent, contractimpl, contracttype, symbol_short, Env, Symbol};
943///
944/// // Define the event using the `contractevent` attribute macro.
945/// #[contractevent]
946/// #[derive(Clone, Default, Debug, Eq, PartialEq)]
947/// pub struct Increment {
948///     // Mark fields as topics, for the value to be included in the events topic list so
949///     // that downstream systems know to index it.
950///     #[topic]
951///     pub change: u32,
952///     // Fields not marked as topics will appear in the events data section.
953///     pub count: u32,
954/// }
955///
956/// #[contracttype]
957/// #[derive(Clone, Default, Debug, Eq, PartialEq)]
958/// pub struct State {
959///     pub count: u32,
960///     pub last_incr: u32,
961/// }
962///
963/// #[contract]
964/// pub struct Contract;
965///
966/// #[contractimpl]
967/// impl Contract {
968///     /// Increment increments an internal counter, and returns the value.
969///     /// Publishes an event about the change in the counter.
970///     pub fn increment(env: Env, incr: u32) -> u32 {
971///         // Get the current count.
972///         let mut state = Self::get_state(env.clone());
973///
974///         // Increment the count.
975///         state.count += incr;
976///         state.last_incr = incr;
977///
978///         // Save the count.
979///         env.storage().persistent().set(&symbol_short!("STATE"), &state);
980///
981///         // Publish an event about the change.
982///         Increment {
983///             change: incr,
984///             count: state.count,
985///         }.publish(&env);
986///
987///         // Return the count to the caller.
988///         state.count
989///     }
990///
991///     /// Return the current state.
992///     pub fn get_state(env: Env) -> State {
993///         env.storage().persistent()
994///             .get(&symbol_short!("STATE"))
995///             .unwrap_or_else(|| State::default()) // If no value set, assume 0.
996///     }
997/// }
998///
999/// #[test]
1000/// fn test() {
1001/// # }
1002/// # #[cfg(feature = "testutils")]
1003/// # fn main() {
1004///     let env = Env::default();
1005///     let contract_id = env.register(Contract, ());
1006///     let client = ContractClient::new(&env, &contract_id);
1007///
1008///     assert_eq!(client.increment(&1), 1);
1009///     assert_eq!(client.increment(&10), 11);
1010///     assert_eq!(
1011///         client.get_state(),
1012///         State {
1013///             count: 11,
1014///             last_incr: 10,
1015///         },
1016///     );
1017/// }
1018/// # #[cfg(not(feature = "testutils"))]
1019/// # fn main() { }
1020/// ```
1021pub use soroban_sdk_macros::contractevent;
1022
1023/// Generates a type that helps build function args for a contract trait.
1024pub use soroban_sdk_macros::contractargs;
1025
1026/// Generates a client for a contract trait.
1027///
1028/// Can be used to create clients for contracts that live outside the current
1029/// crate, using a trait that has been published as a standard or shared
1030/// interface.
1031///
1032/// Primarily useful when needing to generate a client for someone elses
1033/// contract where they have only shared a trait interface.
1034///
1035/// Note that [`contractimpl`] also automatically generates a client, and so it
1036/// is unnecessary to use [`contractclient`] for contracts that live in the
1037/// current crate.
1038///
1039/// Note that [`contractimport`] also automatically generates a client when
1040/// importing someone elses contract where they have shared a .wasm file.
1041///
1042/// ### Examples
1043///
1044/// ```
1045/// use soroban_sdk::{contract, contractclient, contractimpl, vec, symbol_short, BytesN, Env, Symbol, Vec};
1046///
1047/// #[contractclient(name = "Client")]
1048/// pub trait HelloInteface {
1049///     fn hello(env: Env, to: Symbol) -> Vec<Symbol>;
1050/// }
1051///
1052/// #[contract]
1053/// pub struct HelloContract;
1054///
1055/// #[contractimpl]
1056/// impl HelloContract {
1057///     pub fn hello(env: Env, to: Symbol) -> Vec<Symbol> {
1058///         vec![&env, symbol_short!("Hello"), to]
1059///     }
1060/// }
1061///
1062/// #[test]
1063/// fn test() {
1064/// # }
1065/// # #[cfg(feature = "testutils")]
1066/// # fn main() {
1067///     let env = Env::default();
1068///
1069///     // Register the hello contract.
1070///     let contract_id = env.register(HelloContract, ());
1071///
1072///     // Create a client for the hello contract, that was constructed using
1073///     // the trait.
1074///     let client = Client::new(&env, &contract_id);
1075///
1076///     let words = client.hello(&symbol_short!("Dev"));
1077///
1078///     assert_eq!(words, vec![&env, symbol_short!("Hello"), symbol_short!("Dev"),]);
1079/// }
1080/// # #[cfg(not(feature = "testutils"))]
1081/// # fn main() { }
1082pub use soroban_sdk_macros::contractclient;
1083
1084/// Generates a contract spec for a trait or impl.
1085///
1086/// Note that [`contractimpl`] also generates a contract spec and it is in most
1087/// cases not necessary to use this macro.
1088#[doc(hidden)]
1089pub use soroban_sdk_macros::contractspecfn;
1090
1091/// Import a contract from its WASM file, generating a constant holding the
1092/// contract file.
1093///
1094/// Note that [`contractimport`] also automatically imports the contract file
1095/// into a constant, and so it is usually unnecessary to use [`contractfile`]
1096/// directly, unless you specifically want to only load the contract file
1097/// without generating a client for it.
1098///
1099/// ### SHA-256 Verification
1100///
1101/// Unlike [`contractimport`], `contractfile` **requires** a `sha256`
1102/// parameter. The macro computes the SHA-256 hash of the WASM file at compile
1103/// time and produces a compile error if it does not match the provided value.
1104/// The `sha256` argument must be a hex-encoded SHA-256 digest (64 hex chars, no 0x prefix).
1105///
1106/// ```ignore
1107/// soroban_sdk::contractfile!(
1108///     file = "contract_a.wasm",
1109///     sha256 = "d5bc0a5b4...",
1110/// );
1111/// ```
1112pub use soroban_sdk_macros::contractfile;
1113
1114/// Panic with the given error.
1115///
1116/// The first argument in the list must be a reference to an [Env].
1117///
1118/// The second argument is an error value. The error value will be given to any
1119/// calling contract.
1120///
1121/// Equivalent to `panic!`, but with an error value instead of a string. The
1122/// error value will be given to any calling contract.
1123///
1124/// See [`contracterror`] for how to define an error type.
1125#[macro_export]
1126macro_rules! panic_with_error {
1127    ($env:expr, $error:expr) => {{
1128        $env.panic_with_error($error);
1129    }};
1130}
1131
1132#[doc(hidden)]
1133#[deprecated(note = "use panic_with_error!")]
1134#[macro_export]
1135macro_rules! panic_error {
1136    ($env:expr, $error:expr) => {{
1137        $crate::panic_with_error!($env, $error);
1138    }};
1139}
1140
1141/// An internal panic! variant that avoids including the string
1142/// when building for wasm (since it's just pointless baggage).
1143#[cfg(target_family = "wasm")]
1144macro_rules! sdk_panic {
1145    ($_msg:literal) => {
1146        panic!()
1147    };
1148    () => {
1149        panic!()
1150    };
1151}
1152#[cfg(not(target_family = "wasm"))]
1153macro_rules! sdk_panic {
1154    ($msg:literal) => {
1155        panic!($msg)
1156    };
1157    () => {
1158        panic!()
1159    };
1160}
1161
1162/// Assert a condition and panic with the given error if it is false.
1163///
1164/// The first argument in the list must be a reference to an [Env].
1165///
1166/// The second argument is an expression that if resolves to `false` will cause
1167/// a panic with the error in the third argument.
1168///
1169/// The third argument is an error value. The error value will be given to any
1170/// calling contract.
1171///
1172/// Equivalent to `assert!`, but with an error value instead of a string. The
1173/// error value will be given to any calling contract.
1174///
1175/// See [`contracterror`] for how to define an error type.
1176#[macro_export]
1177macro_rules! assert_with_error {
1178    ($env:expr, $cond:expr, $error:expr) => {{
1179        if !($cond) {
1180            $crate::panic_with_error!($env, $error);
1181        }
1182    }};
1183}
1184
1185#[doc(hidden)]
1186pub mod unwrap;
1187
1188mod env;
1189
1190mod address;
1191pub mod address_payload;
1192mod muxed_address;
1193mod symbol;
1194
1195pub use env::{ConversionError, Env};
1196
1197/// Raw value of the Soroban smart contract platform that types can be converted
1198/// to and from for storing, or passing between contracts.
1199///
1200pub use env::Val;
1201
1202/// Used to do conversions between values in the Soroban environment.
1203pub use env::FromVal;
1204/// Used to do conversions between values in the Soroban environment.
1205pub use env::IntoVal;
1206/// Used to do conversions between values in the Soroban environment.
1207pub use env::TryFromVal;
1208/// Used to do conversions between values in the Soroban environment.
1209pub use env::TryIntoVal;
1210
1211// Used by generated code only.
1212#[doc(hidden)]
1213pub use env::EnvBase;
1214#[doc(hidden)]
1215pub use env::Error;
1216#[doc(hidden)]
1217pub use env::MapObject;
1218#[doc(hidden)]
1219pub use env::SymbolStr;
1220#[doc(hidden)]
1221pub use env::VecObject;
1222
1223mod try_from_val_for_contract_fn;
1224#[doc(hidden)]
1225#[allow(deprecated)]
1226pub use try_from_val_for_contract_fn::TryFromValForContractFn;
1227
1228mod into_val_for_contract_fn;
1229#[doc(hidden)]
1230#[allow(deprecated)]
1231pub use into_val_for_contract_fn::IntoValForContractFn;
1232
1233mod spec_shaking;
1234#[doc(hidden)]
1235pub use spec_shaking::SpecShakingMarker;
1236
1237#[doc(hidden)]
1238#[deprecated(note = "use storage")]
1239pub mod data {
1240    #[doc(hidden)]
1241    #[deprecated(note = "use storage::Storage")]
1242    pub use super::storage::Storage as Data;
1243}
1244pub mod auth;
1245#[macro_use]
1246mod bytes;
1247pub mod crypto;
1248pub mod custom_account;
1249pub mod deploy;
1250mod error;
1251pub use error::InvokeError;
1252pub mod events;
1253pub use events::{Event, Topics};
1254pub mod executable_refs;
1255pub mod iter;
1256pub mod ledger;
1257pub mod logs;
1258mod map;
1259pub mod prng;
1260pub mod storage;
1261pub mod token;
1262mod vec;
1263pub use address::{Address, Executable};
1264pub use bytes::{Bytes, BytesN};
1265pub use map::Map;
1266pub use muxed_address::MuxedAddress;
1267pub use symbol::Symbol;
1268pub use vec::Vec;
1269mod num;
1270pub use num::{Duration, Timepoint, I256, U256};
1271mod string;
1272pub use string::String;
1273mod tuple;
1274
1275mod constructor_args;
1276pub use constructor_args::ConstructorArgs;
1277
1278/// Contract executable used for creating a new contract and used in
1279/// `CreateContractHostFnContext`.
1280#[derive(Clone, Debug)]
1281#[contracttype(crate_path = "crate")]
1282pub enum ContractExecutable {
1283    /// Executable specified by the contract instance as a specific Wasm contract code entry identified by its Wasm sha256 hash.
1284    Wasm(BytesN<32>),
1285    /// Executable reference via a persistent storage entry owned by this contract or another contract.
1286    ExternalRef(ContractExecutableRef),
1287}
1288
1289/// Executable referenced via a persistent storage entry owned by a contract,
1290/// either this contract or another contract.
1291///
1292/// The persistent storage entry owned by the `owner` has the `tag` as its key.
1293#[derive(Clone, Debug)]
1294#[contracttype(crate_path = "crate")]
1295pub struct ContractExecutableRef {
1296    pub owner: Address,
1297    pub tag: String,
1298}
1299
1300pub mod xdr;
1301
1302pub mod testutils;
1303
1304mod arbitrary_extra;
1305
1306mod tests;