testnumbat_wasm/
macros.rs

1// Note: Simple macros cannot be placed in testnumbat-wasm-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 core::ops::{
9            Add, AddAssign, BitAnd, BitAndAssign, BitOr, BitOrAssign, BitXor, BitXorAssign, Div,
10            DivAssign, Mul, MulAssign, Rem, RemAssign, Shl, ShlAssign, Shr, ShrAssign, Sub,
11            SubAssign,
12        };
13        use testnumbat_wasm::{
14            api::{
15                BigIntApi, BlockchainApi, CallValueApi, CryptoApi, EllipticCurveApi, ErrorApi,
16                LogApi, ManagedTypeApi, SendApi,
17            },
18            contract_base::{ContractBase, ProxyObjBase},
19            testnumbat_codec::{DecodeError, NestedDecode, NestedEncode, TopDecode},
20            err_msg,
21            dcdt::*,
22            io::*,
23            non_zero_usize,
24            non_zero_util::*,
25            only_owner, require, sc_error,
26            storage::mappers::*,
27            types::{
28                SCResult::{Err, Ok},
29                *,
30            },
31            Box, Vec,
32        }; // TODO: remove at some point, they shouldn't be public
33    };
34}
35
36/// Imports required for deriving serialization and TypeAbi.
37#[macro_export]
38macro_rules! derive_imports {
39    () => {
40        use testnumbat_wasm::{
41            derive::TypeAbi,
42            testnumbat_codec,
43            testnumbat_codec::testnumbat_codec_derive::{
44                NestedDecode, NestedEncode, TopDecode, TopDecodeOrDefault, TopEncode,
45                TopEncodeOrDefault,
46            },
47        };
48    };
49}
50
51/// Compact way of returning a static error message.
52#[macro_export]
53macro_rules! sc_error {
54    ($s:expr) => {
55        testnumbat_wasm::types::SCResult::Err(testnumbat_wasm::types::StaticSCError::from($s)).into()
56    };
57}
58
59/// Equivalent to the `?` operator for SCResult.
60#[deprecated(
61    since = "0.16.0",
62    note = "The `?` operator can now be used on `SCResult`, please use it instead."
63)]
64#[macro_export]
65macro_rules! sc_try {
66    ($s:expr) => {
67        match $s {
68            testnumbat_wasm::types::SCResult::Ok(t) => t,
69            testnumbat_wasm::types::SCResult::Err(e) => {
70                return testnumbat_wasm::types::SCResult::Err(e);
71            },
72        }
73    };
74}
75
76/// Allows us to write Solidity style `require!(<condition>, <error_msg>)` and avoid if statements.
77///
78/// It can only be used in a function that returns `SCResult<_>` where _ can be any type.
79///
80/// ```rust
81/// # use testnumbat_wasm::*;
82/// # use testnumbat_wasm::api::BlockchainApi;
83/// # use testnumbat_wasm::types::{*, SCResult::Ok};
84/// # pub trait ExampleContract: testnumbat_wasm::contract_base::ContractBase
85/// # {
86/// fn only_callable_by_owner(&self) -> SCResult<()> {
87///     require!(self.blockchain().get_caller() == self.blockchain().get_owner_address(), "Caller must be owner");
88///     Ok(())
89/// }
90/// # }
91/// ```
92#[macro_export]
93macro_rules! require {
94    ($expression:expr, $error_msg:expr) => {
95        if (!($expression)) {
96            return sc_error!($error_msg);
97        }
98    };
99}
100
101/// Very compact way of not allowing anyone but the owner to call a function.
102///
103/// It can only be used in a function that returns `SCResult<_>` where _ can be any type.
104///
105/// ```rust
106/// # use testnumbat_wasm::*;
107/// # use testnumbat_wasm::api::BlockchainApi;
108/// # use testnumbat_wasm::types::{*, SCResult::Ok};
109/// # pub trait ExampleContract: testnumbat_wasm::contract_base::ContractBase
110/// # {
111/// fn only_callable_by_owner(&self) -> SCResult<()> {
112///     only_owner!(self, "Caller must be owner");
113///     Ok(())
114/// }
115/// # }
116/// ```
117#[macro_export]
118macro_rules! only_owner {
119    ($trait_self: expr, $error_msg:expr) => {
120        if ($trait_self.blockchain().get_caller() != $trait_self.blockchain().get_owner_address()) {
121            return sc_error!($error_msg);
122        }
123    };
124}
125
126/// Converts usize to NonZeroUsize or returns SCError.
127#[macro_export]
128macro_rules! non_zero_usize {
129    ($input: expr, $error_msg:expr) => {
130        if let Some(nz) = NonZeroUsize::new($input) {
131            nz
132        } else {
133            return sc_error!($error_msg);
134        }
135    };
136}