1#![cfg_attr(not(feature = "std"), no_std)]
2
3#[cfg(feature = "alloc")]
4extern crate alloc;
5
6#[cfg(feature = "alloc")]
7use alloc::vec::Vec;
8
9pub use bobcat_maths::U;
10
11pub type Address = [u8; 20];
12
13pub use bobcat_cd::read_word_slices;
14
15#[cfg(target_arch = "wasm32")]
16mod impls {
17 #[link(wasm_import_module = "vm_hooks")]
18 unsafe extern "C" {
19 #[allow(unused)]
20 pub(crate) fn pay_for_memory_grow(pages: u16);
21 pub(crate) fn write_result(d: *const u8, l: usize);
22 pub(crate) fn read_args(out: *mut u8);
23 pub(crate) fn msg_sender(addr: *mut u8);
24 pub(crate) fn contract_address(addr: *mut u8);
25 pub(crate) fn msg_value(value: *mut u8);
26 pub fn chain_id() -> u64;
27 pub(crate) fn account_code_size(address: *const u8) -> usize;
28 pub(crate) fn block_timestamp() -> u64;
29 }
30}
31
32#[cfg(all(not(target_arch = "wasm32"), feature = "std"))]
33mod impls {
34 use core::{ptr::copy_nonoverlapping, slice::from_raw_parts};
35
36 #[allow(unused)]
37 pub(crate) unsafe fn pay_for_memory_grow(_: u16) {}
38
39 pub(crate) unsafe fn write_result(d: *const u8, l: usize) {
40 println!("{}", const_hex::encode(unsafe { from_raw_parts(d, l) }));
41 }
42
43 pub(crate) unsafe fn read_args(_out: *mut u8) {
44 unimplemented!("read from stdin separately. todo");
45 }
46
47 pub(crate) unsafe fn msg_sender(out: *mut u8) {
48 unsafe { copy_nonoverlapping([0u8; 32].as_ptr(), out, 32) }
49 }
50
51 pub(crate) unsafe fn contract_address(out: *mut u8) {
52 unsafe { copy_nonoverlapping([0u8; 32].as_ptr(), out, 32) }
53 }
54
55 pub(crate) unsafe fn msg_value(out: *mut u8) {
56 unsafe { copy_nonoverlapping([0u8; 32].as_ptr(), out, 32) }
57 }
58
59 pub(crate) unsafe fn chain_id() -> u64 {
60 0
61 }
62
63 pub(crate) unsafe fn account_code_size(_: *const u8) -> usize {
64 0
65 }
66
67 pub(crate) unsafe fn block_timestamp() -> u64 {
68 0
69 }
70}
71
72#[cfg(all(not(target_arch = "wasm32"), not(feature = "std")))]
73mod impls {
74 pub(crate) unsafe fn pay_for_memory_grow(_: u16) {}
75
76 pub(crate) unsafe fn write_result(_: *const u8, _: usize) {}
77
78 pub(crate) unsafe fn read_args(_out: *mut u8) {}
79
80 pub(crate) unsafe fn msg_sender(_: *mut u8) {}
81
82 pub(crate) unsafe fn contract_address(_: *mut u8) {}
83
84 pub(crate) unsafe fn msg_value(_: *mut u8) {}
85
86 pub(crate) unsafe fn chain_id() -> u64 {
87 0
88 }
89
90 pub(crate) unsafe fn account_code_size(_: *const u8) -> usize {
91 0
92 }
93
94 pub(crate) unsafe fn block_timestamp() -> u64 {
95 0
96 }
97}
98
99#[unsafe(no_mangle)]
100#[cfg(not(feature = "dont-define-symbols"))]
101pub unsafe fn mark_used() {
102 unsafe { impls::pay_for_memory_grow(0) }
103 panic!();
104}
105
106pub fn write_result_slice(s: &[u8]) {
107 unsafe { impls::write_result(s.as_ptr(), s.len()) }
108}
109
110pub use bobcat_cd::leftpad_addr;
111
112#[macro_export]
116macro_rules! revert_if_bad_call_vec {
117 ($e:expr) => {{
118 let (rc, rd) = $e;
119 if !rc {
120 $crate::write_result_slice(&rd);
121 return 1;
122 }
123 rd
124 }};
125}
126
127#[macro_export]
128macro_rules! write_result_exit_res {
129 ($ident:expr) => {{
130 match $ident {
131 Ok(v) => {
132 $crate::write_result_slice(&v);
133 0
134 }
135 Err(v) => {
136 $crate::write_result_slice(&v);
137 1
138 }
139 }
140 }};
141}
142
143#[macro_export]
144macro_rules! write_result_exit_create {
145 ($ident:expr) => {{
146 let (addr, b, i) = $ident;
147 if addr != [0u8; 20] {
148 $crate::write_result_slice(&leftpad_addr(addr));
149 0
150 } else {
151 $crate::write_result_slice(&b[..i]);
152 1
153 }
154 }};
155}
156
157#[macro_export]
158macro_rules! write_result_exit_call {
159 ($ident:expr) => {{
160 let (rc, l, v) = $ident;
161 $crate::write_result_slice(&v[..l]);
162 if rc {
163 0
164 } else {
165 1
166 }
167 }};
168}
169
170pub fn read_args<const CAP: usize>(len: usize) -> ([u8; CAP], usize) {
171 assert!(CAP >= len, "cap not enough");
172 let mut b = [0u8; CAP];
173 unsafe { impls::read_args(b.as_mut_ptr()) };
174 (b, len)
175}
176
177#[macro_export]
178macro_rules! read_args_safe {
179 ($len:expr, $max_len:expr) => {{
180 assert!($max_len >= $len);
181 $crate::read_args::<$max_len>($len).0
182 }};
183}
184
185#[cfg(feature = "alloc")]
186pub fn read_args_vec(len: usize) -> Vec<u8> {
187 let mut b = Vec::with_capacity(len);
188 unsafe {
189 impls::read_args(b.as_mut_ptr());
190 b.set_len(len);
191 };
192 b
193}
194
195pub fn msg_sender() -> Address {
196 let mut b = [0u8; 20];
197 unsafe { impls::msg_sender(b.as_mut_ptr()) }
198 b
199}
200
201pub fn contract_address() -> Address {
202 let mut b = [0u8; 20];
203 unsafe { impls::contract_address(b.as_mut_ptr()) }
204 b
205}
206
207pub fn msg_value() -> U {
208 let mut b = [0u8; 32];
209 unsafe { impls::msg_value(b.as_mut_ptr()) }
210 U(b)
211}
212
213pub fn code_size(addr: Address) -> usize {
214 unsafe { impls::account_code_size(addr.as_ptr()) }
215}
216
217pub fn chain_id() -> u64 {
218 unsafe { impls::chain_id() }
219}
220
221pub fn block_timestamp() -> u64 {
222 unsafe { impls::block_timestamp() }
223}