multiversx_sc/
macros.rs

1// Note: Simple macros cannot be placed in multiversx-sc-derive,
2// because Rust "cannot export macro_rules! macros from a `proc-macro` crate type currently".
3
4/// Getting all imports needed for a smart contract.
5#[macro_export]
6macro_rules! imports {
7    () => {
8        use multiversx_sc::imports::*;
9    };
10}
11
12/// Imports required for deriving serialization and TypeAbi.
13#[macro_export]
14macro_rules! derive_imports {
15    () => {
16        use multiversx_sc::derive_imports::*;
17    };
18}
19
20/// Compact way of returning a static error message.
21#[deprecated(
22    since = "0.48.0",
23    note = "Use `sc_panic!` instead, which terminates immediately."
24)]
25#[macro_export]
26macro_rules! sc_error {
27    ($s:expr) => {
28        multiversx_sc::types::SCResult::Err(multiversx_sc::types::StaticSCError::from($s)).into()
29    };
30}
31
32/// Allows us to write Solidity style `require!(<condition>, <error_msg>)` and avoid if statements.
33///
34/// It can only be used in a function that returns `SCResult<_>` where _ can be any type.
35///
36/// Example:
37///
38/// ```rust
39/// # use multiversx_sc::require_old;
40/// # use multiversx_sc::types::{*, SCResult::Ok};
41/// # pub trait ExampleContract: multiversx_sc::contract_base::ContractBase
42/// # {
43/// fn only_accept_positive_old(&self, x: i32) -> SCResult<()> {
44///     require_old!(x > 0, "only positive values accepted");
45///     Ok(())
46/// }
47/// # }
48/// ```
49#[deprecated(
50    since = "0.48.0",
51    note = "Use `require!` instead, which terminates immediately."
52)]
53#[macro_export]
54macro_rules! require_old {
55    ($expression:expr, $error_msg:expr) => {
56        if (!($expression)) {
57            return multiversx_sc::sc_error!($error_msg);
58        }
59    };
60}
61
62#[macro_export]
63macro_rules! sc_panic {
64    ($msg:tt, $($arg:expr),+ $(,)?) => {{
65        let mut ___buffer___ =
66            multiversx_sc::types::ManagedBufferBuilder::<Self::Api>::new_from_slice(&[]);
67        multiversx_sc::derive::format_receiver_args!(___buffer___, $msg, $($arg),+);
68        multiversx_sc::contract_base::ErrorHelper::<Self::Api>::signal_error_with_message(___buffer___.into_managed_buffer());
69    }};
70    ($msg:expr $(,)?) => {
71        multiversx_sc::contract_base::ErrorHelper::<Self::Api>::signal_error_with_message($msg);
72    };
73}
74
75/// Allows us to write Solidity style `require!(<condition>, <error_msg>)` and avoid if statements.
76///
77/// The most common way to use it is to provide a string message with optional format arguments.
78///
79/// It is also possible to give the error as a variable of types such as `&str`, `&[u8]` or `ManagedBuffer`.
80///
81/// Examples:
82///
83/// ```rust
84/// # use multiversx_sc::{types::ManagedBuffer, require};
85/// # pub trait ExampleContract: multiversx_sc::contract_base::ContractBase
86/// # {
87/// fn only_accept_positive(&self, x: i32) {
88///     require!(x > 0, "only positive values accepted");
89/// }
90///
91/// fn only_accept_negative(&self, x: i32) {
92///     require!(x < 0, "only negative values accepted, {} is not negative", x);
93/// }
94///
95/// fn only_accept_zero(&self, x: i32, message: &ManagedBuffer<Self::Api>) {
96///     require!(x == 0, message,);
97/// }
98/// # }
99/// ```
100#[macro_export]
101macro_rules! require {
102    ($expression:expr, $($msg_tokens:tt),+  $(,)?) => {
103        if (!($expression)) {
104            multiversx_sc::sc_panic!($($msg_tokens),+);
105        }
106    };
107}
108
109#[macro_export]
110macro_rules! sc_print {
111    ($msg:tt, $($arg:expr),* $(,)?) => {{
112        let mut ___buffer___ =
113            <<Self::Api as multiversx_sc::api::PrintApi>::PrintApiImpl as multiversx_sc::api::PrintApiImpl>::Buffer::default();
114        multiversx_sc::derive::format_receiver_args!(___buffer___, $msg, $($arg),*);
115        <<Self::Api as multiversx_sc::api::PrintApi>::PrintApiImpl as multiversx_sc::api::PrintApiImpl>::print_buffer(
116            &<Self::Api as multiversx_sc::api::PrintApi>::print_api_impl(),
117            ___buffer___,
118        );
119    }};
120}
121
122#[macro_export]
123macro_rules! sc_format {
124    ($msg:tt, $($arg:expr),+ $(,)?) => {{
125        let mut ___buffer___ =
126            multiversx_sc::types::ManagedBufferBuilder::<Self::Api>::new_from_slice(&[]);
127        multiversx_sc::derive::format_receiver_args!(___buffer___, $msg, $($arg),+);
128        ___buffer___.into_managed_buffer()
129    }};
130    ($msg:expr $(,)?) => {{
131        multiversx_sc::types::ManagedBuffer::new_from_bytes($msg.as_bytes())
132    }};
133}
134
135/// Equivalent to the `?` operator for SCResult.
136#[deprecated(
137    since = "0.16.0",
138    note = "The `?` operator can now be used on `SCResult`, please use it instead."
139)]
140#[macro_export]
141macro_rules! sc_try {
142    ($s:expr) => {
143        match $s {
144            multiversx_sc::types::SCResult::Ok(t) => t,
145            multiversx_sc::types::SCResult::Err(e) => {
146                return multiversx_sc::types::SCResult::Err(e);
147            },
148        }
149    };
150}
151
152/// Very compact way of not allowing anyone but the owner to call a function.
153///
154/// It can only be used in a function that returns `SCResult<_>` where _ can be any type.
155///
156/// ```rust
157/// # use multiversx_sc::*;
158/// # use multiversx_sc::api::BlockchainApi;
159/// # use multiversx_sc::types::{*, SCResult::Ok};
160/// # pub trait ExampleContract: multiversx_sc::contract_base::ContractBase
161/// # {
162/// fn only_callable_by_owner(&self) -> SCResult<()> {
163///     only_owner!(self, "Caller must be owner");
164///     Ok(())
165/// }
166/// # }
167/// ```
168#[deprecated(
169    since = "0.26.0",
170    note = "Replace with the `#[only_owner]` attribute that can be placed on an endpoint. That one is more compact and shows up in the ABI."
171)]
172#[macro_export]
173macro_rules! only_owner {
174    ($trait_self: expr, $error_msg:expr) => {
175        if ($trait_self.blockchain().get_caller() != $trait_self.blockchain().get_owner_address()) {
176            return multiversx_sc::sc_error!($error_msg);
177        }
178    };
179}
180
181/// Converts usize to NonZeroUsize or returns SCError.
182#[macro_export]
183macro_rules! non_zero_usize {
184    ($input: expr, $error_msg:expr) => {
185        NonZeroUsize::new($input).unwrap_or_else(|| sc_panic!($error_msg))
186    };
187}