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