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