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