1#![no_std]
2
3extern crate alloc;
5pub use alloc::boxed::Box;
6pub use alloc::string::String;
7pub use alloc::vec::Vec;
8
9pub use numbat_codec;
10
11pub mod abi;
12pub mod err_msg;
13pub mod hex_call_data;
14pub mod io;
15pub mod non_zero_util;
16mod proxy;
17pub mod storage;
18pub mod types;
19
20pub use hex_call_data::*;
21pub use io::*;
22pub use proxy::OtherContractHandle;
23pub use storage::{storage_get, storage_set};
24pub use types::*;
25
26use core::ops::{Add, Div, Mul, Neg, Rem, Sub};
27use core::ops::{AddAssign, DivAssign, MulAssign, RemAssign, SubAssign};
28use core::ops::{BitAnd, BitOr, BitXor, Shl, Shr};
29use core::ops::{BitAndAssign, BitOrAssign, BitXorAssign, ShlAssign, ShrAssign};
30
31pub trait ContractHookApi<BigInt, BigUint>: Sized
38where
39 BigInt: numbat_codec::NestedEncode + 'static,
40 BigUint: numbat_codec::NestedEncode + 'static,
41{
42 fn get_sc_address(&self) -> Address;
43
44 fn get_owner_address(&self) -> Address;
45
46 fn get_caller(&self) -> Address;
47
48 fn get_balance(&self, address: &Address) -> BigUint;
49
50 fn get_sc_balance(&self) -> BigUint {
51 self.get_balance(&self.get_sc_address())
52 }
53
54 fn storage_store_slice_u8(&self, key: &[u8], value: &[u8]);
55
56 fn storage_load_len(&self, key: &[u8]) -> usize;
57
58 fn storage_load_vec_u8(&self, key: &[u8]) -> Vec<u8>;
59
60 fn storage_load_boxed_bytes(&self, key: &[u8]) -> BoxedBytes {
61 self.storage_load_vec_u8(key).into()
62 }
63
64 fn storage_store_bytes32(&self, key: &[u8], value: &[u8; 32]);
65
66 fn storage_load_bytes32(&self, key: &[u8]) -> [u8; 32];
67
68 fn storage_store_big_uint(&self, key: &[u8], value: &BigUint);
69
70 fn storage_load_big_uint(&self, key: &[u8]) -> BigUint;
71
72 fn storage_store_big_uint_raw(&self, key: &[u8], handle: i32);
73
74 fn storage_load_big_uint_raw(&self, key: &[u8]) -> i32;
75
76 fn storage_store_big_int(&self, key: &[u8], value: &BigInt);
77
78 fn storage_load_big_int(&self, key: &[u8]) -> BigInt;
79
80 fn storage_store_u64(&self, key: &[u8], value: u64);
81
82 fn storage_store_i64(&self, key: &[u8], value: i64);
83
84 fn storage_load_u64(&self, key: &[u8]) -> u64;
85
86 fn storage_load_i64(&self, key: &[u8]) -> i64;
87
88 #[inline]
89 fn storage_load_cumulated_validator_reward(&self) -> BigUint {
90 self.storage_load_big_uint(storage::protected_keys::NUMBAT_REWARD_KEY)
91 }
92
93 fn get_call_value_big_uint(&self) -> BigUint;
94
95 fn get_dcdt_value_big_uint(&self) -> BigUint;
96
97 fn get_dcdt_token_name(&self) -> Vec<u8>;
98
99 fn send_tx(&self, to: &Address, amount: &BigUint, data: &[u8]);
100
101 fn async_call(&self, to: &Address, amount: &BigUint, data: &[u8]);
102
103 fn deploy_contract(
104 &self,
105 gas: u64,
106 amount: &BigUint,
107 code: &BoxedBytes,
108 code_metadata: CodeMetadata,
109 arg_buffer: &ArgBuffer,
110 ) -> Address;
111
112 fn get_tx_hash(&self) -> H256;
113
114 fn get_gas_left(&self) -> u64;
115
116 fn get_block_timestamp(&self) -> u64;
117
118 fn get_block_nonce(&self) -> u64;
119
120 fn get_block_round(&self) -> u64;
121
122 fn get_block_epoch(&self) -> u64;
123
124 fn get_block_random_seed(&self) -> Box<[u8; 48]>;
125
126 fn get_prev_block_timestamp(&self) -> u64;
127
128 fn get_prev_block_nonce(&self) -> u64;
129
130 fn get_prev_block_round(&self) -> u64;
131
132 fn get_prev_block_epoch(&self) -> u64;
133
134 fn get_prev_block_random_seed(&self) -> Box<[u8; 48]>;
135
136 fn sha256(&self, data: &[u8]) -> H256;
137
138 fn keccak256(&self, data: &[u8]) -> H256;
139}
140
141pub trait ContractIOApi<BigInt, BigUint>: Clone {
144 fn get_num_arguments(&self) -> i32;
145
146 #[inline(never)] fn check_num_arguments(&self, expected: i32) {
148 let nr_args = self.get_num_arguments();
149 if nr_args != expected {
150 self.signal_error(err_msg::ARG_WRONG_NUMBER);
151 }
152 }
153
154 fn check_not_payable(&self);
155
156 fn get_argument_len(&self, arg_index: i32) -> usize;
157
158 fn copy_argument_to_slice(&self, arg_index: i32, slice: &mut [u8]);
159
160 fn get_argument_vec_u8(&self, arg_index: i32) -> Vec<u8>;
161
162 fn get_argument_boxed_bytes(&self, arg_index: i32) -> BoxedBytes {
163 self.get_argument_vec_u8(arg_index).into()
164 }
165
166 fn get_argument_big_int(&self, arg_id: i32) -> BigInt;
167
168 fn get_argument_big_uint(&self, arg_id: i32) -> BigUint;
169
170 fn get_argument_big_int_raw(&self, arg_id: i32) -> i32;
171
172 fn get_argument_big_uint_raw(&self, arg_id: i32) -> i32;
173
174 fn get_argument_u64(&self, arg_id: i32) -> u64;
175
176 fn get_argument_i64(&self, arg_id: i32) -> i64;
177
178 fn finish_slice_u8(&self, slice: &[u8]);
179
180 fn finish_big_int(&self, b: &BigInt);
181
182 fn finish_big_uint(&self, b: &BigUint);
183
184 fn finish_big_int_raw(&self, handle: i32);
185
186 fn finish_big_uint_raw(&self, handle: i32);
187
188 fn finish_u64(&self, value: u64);
189
190 fn finish_i64(&self, value: i64);
191
192 fn signal_error(&self, message: &[u8]) -> !;
193
194 fn write_log(&self, topics: &[[u8; 32]], data: &[u8]);
195}
196
197pub trait BigUintApi:
205 Sized
206 + From<u64>
207 + From<u32>
208 + From<usize>
209 + Clone
210 + Add<Output = Self>
211 + AddAssign
212 + Sub<Output = Self>
213 + SubAssign
214 + Mul<Output = Self>
215 + MulAssign
216 + Div<Output = Self>
217 + DivAssign
218 + Rem<Output = Self>
219 + RemAssign
220 + BitAnd<Output = Self>
221 + BitAndAssign
222 + BitOr<Output = Self>
223 + BitOrAssign
224 + BitXor<Output = Self>
225 + BitXorAssign
226 + Shr<usize, Output = Self>
227 + ShrAssign<usize>
228 + Shl<usize, Output = Self>
229 + ShlAssign<usize>
230 + PartialEq<Self>
231 + Eq
232 + PartialOrd<Self>
233 + Ord
234 + PartialEq<u64>
235 + PartialOrd<u64>
236 + numbat_codec::NestedEncode
237 + numbat_codec::TopEncode
238 + numbat_codec::NestedDecode
239 + numbat_codec::TopDecode
240 + abi::TypeAbi
241{
242 fn zero() -> Self {
243 0u64.into()
244 }
245
246 fn byte_length(&self) -> i32;
247
248 fn copy_to_slice_big_endian(&self, slice: &mut [u8]) -> i32;
249
250 fn copy_to_array_big_endian_pad_right(&self, target: &mut [u8; 32]);
251
252 fn to_bytes_be(&self) -> Vec<u8>;
253
254 fn to_bytes_be_pad_right(&self, nr_bytes: usize) -> Option<Vec<u8>>;
255
256 fn from_bytes_be(bytes: &[u8]) -> Self;
257}
258
259pub enum Sign {
261 Minus,
262 NoSign,
263 Plus,
264}
265
266pub trait BigIntApi<BigUint>:
268 Sized
269 + From<BigUint>
270 + From<i64>
271 + From<i32>
272 + Clone
273 + Add<Output = Self>
274 + AddAssign
275 + Sub<Output = Self>
276 + SubAssign
277 + Mul<Output = Self>
278 + MulAssign
279 + Div<Output = Self>
280 + DivAssign
281 + Rem<Output = Self>
282 + RemAssign
283 + Neg
284 + PartialEq<Self>
285 + Eq
286 + PartialOrd<Self>
287 + Ord
288 + PartialEq<i64>
289 + PartialOrd<i64>
290 + numbat_codec::NestedEncode
291 + numbat_codec::TopEncode
292 + numbat_codec::NestedDecode
293 + numbat_codec::TopDecode
294 + abi::TypeAbi
295{
296 fn zero() -> Self {
297 0i64.into()
298 }
299
300 fn abs_uint(&self) -> BigUint;
301
302 fn sign(&self) -> Sign;
303
304 fn to_signed_bytes_be(&self) -> Vec<u8>;
305
306 fn from_signed_bytes_be(bytes: &[u8]) -> Self;
307}
308
309pub trait CallableContract<A> {
311 fn call(&self, fn_name: &[u8]) -> bool;
312
313 fn abi(&self, include_modules: bool) -> abi::ContractAbi;
314
315 fn clone_contract(&self) -> Box<dyn CallableContract<A>>;
316
317 fn into_api(self: Box<Self>) -> A;
318}
319
320#[macro_export]
323macro_rules! contract_proxy {
324 ($s:expr, $address:expr, $proxy_trait:ident) => {
325 $s.contract_proxy($address) as Box<dyn $proxy_trait<BigInt, BigUint>>
326 };
327}
328
329#[macro_export]
331macro_rules! imports {
332 () => {
333 use core::ops::{Add, Div, Mul, Rem, Sub};
334 use core::ops::{AddAssign, DivAssign, MulAssign, RemAssign, SubAssign};
335 use core::ops::{BitAnd, BitOr, BitXor, Shl, Shr};
336 use core::ops::{BitAndAssign, BitOrAssign, BitXorAssign, ShlAssign, ShrAssign};
337 use numbat_wasm::numbat_codec::{DecodeError, NestedDecode, NestedEncode, TopDecode};
338 use numbat_wasm::err_msg;
339 use numbat_wasm::io::*;
340 use numbat_wasm::non_zero_util::*;
341 use numbat_wasm::types::*;
342 use numbat_wasm::{Address, H256};
343 use numbat_wasm::{
344 AsyncCallError, AsyncCallResult, BigIntApi, BigUintApi, ContractHookApi, ContractIOApi,
345 OtherContractHandle,
346 };
347 use numbat_wasm::{BorrowedMutStorage, Box, BoxedBytes, Queue, VarArgs, Vec};
348 use numbat_wasm::{SCError, SCResult, SCResult::Err, SCResult::Ok};
349 };
350}
351
352#[macro_export]
354macro_rules! derive_imports {
355 () => {
356 use numbat_wasm::numbat_codec;
357 use numbat_wasm::numbat_codec::numbat_codec_derive::{
358 NestedDecode, NestedEncode, TopDecode, TopEncode,
359 };
360 use numbat_wasm_derive::TypeAbi;
361 };
362}
363
364#[macro_export]
366macro_rules! sc_error {
367 ($s:expr) => {
368 numbat_wasm::SCResult::Err(numbat_wasm::SCError::from($s.as_bytes()))
369 };
370}
371
372#[macro_export]
374macro_rules! sc_try {
375 ($s:expr) => {
376 match $s {
377 numbat_wasm::SCResult::Ok(t) => t,
378 numbat_wasm::SCResult::Err(e) => {
379 return numbat_wasm::SCResult::Err(e);
380 },
381 }
382 };
383}
384
385#[macro_export]
403macro_rules! require {
404 ($expression:expr, $error_msg:expr) => {
405 if (!($expression)) {
406 return sc_error!($error_msg);
407 }
408 };
409}
410
411#[macro_export]
429macro_rules! only_owner {
430 ($trait_self: expr, $error_msg:expr) => {
431 if ($trait_self.get_caller() != $trait_self.get_owner_address()) {
432 return sc_error!($error_msg);
433 }
434 };
435}
436
437#[macro_export]
439macro_rules! mut_storage (
440 ($t:ty) => (
441 BorrowedMutStorage<T, BigInt, BigUint, $t>
442 )
443);
444
445#[macro_export]
447macro_rules! non_zero_usize {
448 ($input: expr, $error_msg:expr) => {
449 if let Some(nz) = NonZeroUsize::new($input) {
450 nz
451 } else {
452 return sc_error!($error_msg);
453 }
454 };
455}