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
13#[cfg(target_arch = "wasm32")]
14mod impls {
15 #[link(wasm_import_module = "vm_hooks")]
16 unsafe extern "C" {
17 #[allow(unused)]
18 pub(crate) fn pay_for_memory_grow(pages: u16);
19 pub(crate) fn write_result(d: *const u8, l: usize);
20 pub(crate) fn read_args(out: *mut u8);
21 pub(crate) fn msg_sender(addr: *mut u8);
22 pub(crate) fn contract_address(addr: *mut u8);
23 pub(crate) fn msg_value(value: *mut u8);
24 pub(crate) fn msg_reentrant() -> bool;
25 pub fn chain_id() -> u64;
26 pub(crate) fn account_code_size(address: *const u8) -> usize;
27 }
28}
29
30#[cfg(all(not(target_arch = "wasm32"), feature = "std"))]
31mod impls {
32 use core::{ptr::copy_nonoverlapping, slice::from_raw_parts};
33
34 #[allow(unused)]
35 pub(crate) unsafe fn pay_for_memory_grow(_: u16) {}
36
37 pub(crate) unsafe fn write_result(d: *const u8, l: usize) {
38 println!("{}", const_hex::encode(unsafe { from_raw_parts(d, l) }));
39 }
40
41 pub(crate) unsafe fn read_args(_out: *mut u8) {
42 unimplemented!("read from stdin separately. todo");
43 }
44
45 pub(crate) unsafe fn msg_sender(out: *mut u8) {
46 unsafe { copy_nonoverlapping([0u8; 32].as_ptr(), out, 32) }
47 }
48
49 pub(crate) unsafe fn contract_address(out: *mut u8) {
50 unsafe { copy_nonoverlapping([0u8; 32].as_ptr(), out, 32) }
51 }
52
53 pub(crate) unsafe fn msg_value(out: *mut u8) {
54 unsafe { copy_nonoverlapping([0u8; 32].as_ptr(), out, 32) }
55 }
56
57 pub(crate) unsafe fn msg_reentrant() -> bool {
58 false
59 }
60
61 pub(crate) unsafe fn chain_id() -> u64 {
62 0
63 }
64
65 pub(crate) unsafe fn account_code_size(_: *const u8) -> usize {
66 0
67 }
68}
69
70#[cfg(all(not(target_arch = "wasm32"), not(feature = "std")))]
71mod impls {
72 pub(crate) unsafe fn pay_for_memory_grow(_: u16) {}
73
74 pub(crate) unsafe fn write_result(_: *const u8, _: usize) {}
75
76 pub(crate) unsafe fn read_args(_out: *mut u8) {}
77
78 pub(crate) unsafe fn msg_sender(_: *mut u8) {}
79
80 pub(crate) unsafe fn contract_address(_: *mut u8) {}
81
82 pub(crate) unsafe fn msg_value(_: *mut u8) {}
83
84 pub(crate) unsafe fn msg_reentrant() -> bool {
85 false
86 }
87
88 pub(crate) unsafe fn chain_id() -> u64 {
89 0
90 }
91
92 pub(crate) unsafe fn account_code_size(_: *const u8) -> usize {
93 0
94 }
95}
96
97#[unsafe(no_mangle)]
98#[cfg(not(feature = "dont-define-symbols"))]
99pub unsafe fn mark_used() {
100 unsafe { impls::pay_for_memory_grow(0) }
101 panic!();
102}
103
104pub fn write_result(s: &[u8]) {
105 unsafe { impls::write_result(s.as_ptr(), s.len()) }
106}
107
108pub fn read_args<const CAP: usize>(len: usize) -> ([u8; CAP], usize) {
109 assert!(CAP >= len, "cap not enough");
110 let mut b = [0u8; CAP];
111 unsafe { impls::read_args(b.as_mut_ptr()) };
112 (b, len)
113}
114
115#[macro_export]
116macro_rules! read_args_safe {
117 ($len:expr, $max_len:expr) => {{
118 assert!($max_len >= $len);
119 $crate::read_args::<$max_len>($len).0
120 }};
121}
122
123#[cfg(feature = "alloc")]
124pub fn read_args_vec(len: usize) -> Vec<u8> {
125 let mut b = Vec::with_capacity(len);
126 unsafe {
127 impls::read_args(b.as_mut_ptr());
128 b.set_len(len);
129 };
130 b
131}
132
133pub fn msg_sender() -> Address {
134 let mut b = [0u8; 20];
135 unsafe { impls::msg_sender(b.as_mut_ptr()) }
136 b
137}
138
139pub fn contract_address() -> Address {
140 let mut b = [0u8; 20];
141 unsafe { impls::contract_address(b.as_mut_ptr()) }
142 b
143}
144
145pub fn msg_value() -> U {
146 let mut b = [0u8; 32];
147 unsafe { impls::msg_value(b.as_mut_ptr()) }
148 U(b)
149}
150
151pub fn msg_reentrant() -> bool {
152 unsafe { impls::msg_reentrant() }
153}
154
155pub fn code_size(addr: Address) -> usize {
156 unsafe { impls::account_code_size(addr.as_ptr()) }
157}
158
159pub fn chain_id() -> u64 {
160 unsafe { impls::chain_id() }
161}