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;