1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
use crate::{TxContext, TxPanic};
use alloc::vec::Vec;
use elrond_wasm::api::{BigIntApi, Handle, ManagedBufferApi, StorageReadApi, StorageWriteApi};
use num_bigint::{BigInt, BigUint, Sign};
use num_traits::ToPrimitive;
impl StorageReadApi for TxContext {
fn storage_load_len(&self, key: &[u8]) -> usize {
self.storage_load_vec_u8(key).len()
}
fn storage_load_vec_u8(&self, key: &[u8]) -> Vec<u8> {
let tx_output = self.tx_output_cell.borrow();
match tx_output.contract_storage.get(&key.to_vec()) {
None => Vec::with_capacity(0),
Some(value) => value.clone(),
}
}
fn storage_load_big_uint_raw(&self, key: &[u8]) -> Handle {
let bytes = self.storage_load_vec_u8(key);
let bi = BigInt::from_bytes_be(Sign::Plus, bytes.as_slice());
let mut tx_output = self.tx_output_cell.borrow_mut();
tx_output.managed_types.big_int_map.insert_new_handle(bi)
}
fn storage_load_managed_buffer_raw(&self, key_handle: Handle) -> Handle {
let key_bytes = self.mb_to_boxed_bytes(key_handle);
let bytes = self.storage_load_vec_u8(key_bytes.as_slice());
self.mb_new_from_bytes(bytes.as_slice())
}
fn storage_load_managed_buffer_len(&self, key_handle: Handle) -> usize {
let key_bytes = self.mb_to_boxed_bytes(key_handle);
let bytes = self.storage_load_vec_u8(key_bytes.as_slice());
bytes.len()
}
fn storage_load_u64(&self, key: &[u8]) -> u64 {
let value = self.storage_load_vec_u8(key);
let bu = BigUint::from_bytes_be(value.as_slice());
if let Some(v) = bu.to_u64() {
v
} else {
std::panic::panic_any(TxPanic {
status: 10,
message: b"storage value out of range".to_vec(),
})
}
}
fn storage_load_i64(&self, key: &[u8]) -> i64 {
let value = self.storage_load_vec_u8(key);
let bi = BigInt::from_signed_bytes_be(value.as_slice());
if let Some(v) = bi.to_i64() {
v
} else {
std::panic::panic_any(TxPanic {
status: 10,
message: b"storage value out of range".to_vec(),
})
}
}
}
impl StorageWriteApi for TxContext {
fn storage_store_slice_u8(&self, key: &[u8], value: &[u8]) {
if key.starts_with(&b"ELROND"[..]) {
std::panic::panic_any(TxPanic {
status: 10,
message: b"cannot write to storage under Elrond reserved key".to_vec(),
});
}
let mut tx_output = self.tx_output_cell.borrow_mut();
tx_output
.contract_storage
.insert(key.to_vec(), value.to_vec());
}
fn storage_store_big_uint_raw(&self, key: &[u8], handle: i32) {
self.storage_store_slice_u8(key, self.bi_get_signed_bytes(handle).as_slice());
}
fn storage_store_managed_buffer_raw(&self, key_handle: Handle, value_handle: Handle) {
let key_bytes = self.mb_to_boxed_bytes(key_handle);
let value_bytes = self.mb_to_boxed_bytes(value_handle);
self.storage_store_slice_u8(key_bytes.as_slice(), value_bytes.as_slice());
}
fn storage_store_managed_buffer_clear(&self, key_handle: Handle) {
let key_bytes = self.mb_to_boxed_bytes(key_handle);
self.storage_store_slice_u8(key_bytes.as_slice(), &[]);
}
fn storage_store_u64(&self, key: &[u8], value: u64) {
if value == 0 {
self.storage_store_slice_u8(key, &[]);
} else {
self.storage_store_slice_u8(key, &BigUint::from(value).to_bytes_be());
}
}
fn storage_store_i64(&self, key: &[u8], value: i64) {
if value == 0 {
self.storage_store_slice_u8(key, &[]);
} else {
self.storage_store_slice_u8(key, &BigInt::from(value).to_signed_bytes_be());
}
}
}