sails_rs/gstd/
syscalls.rs1use crate::prelude::*;
2
3pub struct Syscall;
19
20#[cfg(target_arch = "wasm32")]
21impl Syscall {
22 pub fn message_id() -> MessageId {
23 ::gcore::msg::id()
24 }
25
26 pub fn message_size() -> usize {
27 ::gcore::msg::size()
28 }
29
30 pub fn message_source() -> ActorId {
31 ::gcore::msg::source()
32 }
33
34 pub fn message_value() -> ValueUnit {
35 ::gcore::msg::value()
36 }
37
38 pub fn reply_to() -> Result<MessageId, gcore::errors::Error> {
39 ::gcore::msg::reply_to()
40 }
41
42 pub fn reply_code() -> Result<gcore::errors::ReplyCode, gcore::errors::Error> {
43 ::gcore::msg::reply_code()
44 }
45
46 #[cfg(not(feature = "ethexe"))]
47 pub fn signal_from() -> Result<MessageId, gcore::errors::Error> {
48 ::gcore::msg::signal_from()
49 }
50
51 #[cfg(not(feature = "ethexe"))]
52 pub fn signal_code() -> Result<Option<::gcore::errors::SignalCode>, gcore::errors::Error> {
53 ::gcore::msg::signal_code()
54 }
55
56 pub fn program_id() -> ActorId {
57 ::gcore::exec::program_id()
58 }
59
60 pub fn block_height() -> u32 {
61 ::gcore::exec::block_height()
62 }
63
64 pub fn block_timestamp() -> u64 {
65 ::gcore::exec::block_timestamp()
66 }
67
68 pub fn value_available() -> ValueUnit {
69 ::gcore::exec::value_available()
70 }
71
72 pub fn gas_available() -> GasUnit {
73 ::gcore::exec::gas_available()
74 }
75
76 pub fn env_vars() -> ::gcore::EnvVars {
77 ::gcore::exec::env_vars()
78 }
79
80 pub fn exit(inheritor_id: ActorId) -> ! {
81 ::gcore::exec::exit(inheritor_id)
82 }
83
84 pub fn panic(data: &[u8]) -> ! {
85 ::gcore::ext::panic(data)
86 }
87
88 pub fn read_bytes() -> Result<Vec<u8>, ::gcore::errors::Error> {
89 let mut result = vec![0u8; ::gcore::msg::size()];
90 ::gcore::msg::read(result.as_mut())?;
91 Ok(result)
92 }
93
94 #[cfg(not(feature = "ethexe"))]
95 pub fn system_reserve_gas(amount: GasUnit) -> Result<(), ::gcore::errors::Error> {
96 ::gcore::exec::system_reserve_gas(amount)
97 }
98}
99
100#[cfg(not(target_arch = "wasm32"))]
101#[cfg(not(feature = "std"))]
102macro_rules! syscall_unimplemented {
103 ($($name:ident( $( $param:ident : $ty:ty ),* ) -> $type:ty),* $(,)?) => {
104 impl Syscall {
105 $(
106 pub fn $name($( $param: $ty ),* ) -> $type {
107 unimplemented!("{ERROR}")
108 }
109 )*
110 }
111 };
112}
113
114#[cfg(not(target_arch = "wasm32"))]
115#[cfg(not(feature = "std"))]
116const ERROR: &str = "Syscall is implemented only for the wasm32 architecture and the std future";
117
118#[cfg(not(target_arch = "wasm32"))]
119#[cfg(not(feature = "std"))]
120syscall_unimplemented!(
121 message_id() -> MessageId,
122 message_size() -> usize,
123 message_source() -> ActorId,
124 message_value() -> ValueUnit,
125 reply_to() -> Result<MessageId, gcore::errors::Error>,
126 reply_code() -> Result<ReplyCode, gcore::errors::Error>,
127 signal_from() -> Result<MessageId, gcore::errors::Error>,
128 signal_code() -> Result<Option<SignalCode>, gcore::errors::Error>,
129 program_id() -> ActorId,
130 block_height() -> u32,
131 block_timestamp() -> u64,
132 value_available() -> ValueUnit,
133 gas_available() -> GasUnit,
134 env_vars() -> ::gcore::EnvVars,
135 exit(_inheritor_id: ActorId) -> !,
136 panic(_data: &[u8]) -> !,
137 read_bytes() -> Result<Vec<u8>, gcore::errors::Error>,
138 system_reserve_gas(_amount: GasUnit) -> Result<(), ::gcore::errors::Error>,
139);
140
141#[cfg(not(target_arch = "wasm32"))]
142#[cfg(feature = "std")]
143const _: () = {
144 use core::cell::RefCell;
145 use paste::paste;
146 use std::thread_local;
147
148 macro_rules! syscall_struct_impl {
149 ($($name:ident() -> $type:ty),* $(,)?) => {
150 #[derive(Clone)]
151 struct SyscallState {
152 $(
153 $name: $type,
154 )*
155 }
156
157 thread_local! {
158 static SYSCALL_STATE: RefCell<SyscallState> = RefCell::new(SyscallState::default());
159 }
160
161 impl Syscall {
162 $(
163 pub fn $name() -> $type {
164 SYSCALL_STATE.with_borrow(|state| state.$name.clone())
165 }
166 )*
167 }
168
169 impl Syscall {
170 $(
171 paste! {
172 pub fn [<with_ $name>]($name: $type) {
173 SYSCALL_STATE.with_borrow_mut(|state| state.$name = $name);
174 }
175 }
176 )*
177 }
178 };
179 }
180
181 syscall_struct_impl!(
182 message_id() -> MessageId,
183 message_size() -> usize,
184 message_source() -> ActorId,
185 message_value() -> ValueUnit,
186 reply_to() -> Result<MessageId, gcore::errors::Error>,
187 reply_code() -> Result<ReplyCode, gcore::errors::Error>,
188 signal_from() -> Result<MessageId, gcore::errors::Error>,
189 signal_code() -> Result<Option<SignalCode>, gcore::errors::Error>,
190 program_id() -> ActorId,
191 block_height() -> u32,
192 block_timestamp() -> u64,
193 value_available() -> ValueUnit,
194 gas_available() -> GasUnit,
195 read_bytes() -> Result<Vec<u8>, gcore::errors::Error>,
196 );
197
198 impl Default for SyscallState {
199 fn default() -> Self {
200 use gear_core_errors::{ExecutionError, ExtError};
201
202 Self {
203 message_id: MessageId::default(),
204 message_size: 0,
205 message_source: ActorId::default(),
206 message_value: 0,
207 reply_to: Err(ExtError::Execution(ExecutionError::NoReplyContext).into()),
208 reply_code: Err(ExtError::Execution(ExecutionError::NoReplyContext).into()),
209 signal_from: Err(ExtError::Execution(ExecutionError::NoSignalContext).into()),
210 signal_code: Err(ExtError::Execution(ExecutionError::NoSignalContext).into()),
211 program_id: ActorId::default(),
212 block_height: 0,
213 block_timestamp: 0,
214 value_available: 0,
215 gas_available: 0,
216 read_bytes: Err(::gcore::errors::Error::SyscallUsage),
217 }
218 }
219 }
220
221 impl Syscall {
222 pub fn env_vars() -> ::gcore::EnvVars {
223 ::gcore::EnvVars {
224 performance_multiplier: ::gcore::Percent::new(100),
225 existential_deposit: 1_000_000_000_000,
226 mailbox_threshold: 3000,
227 gas_multiplier: ::gcore::GasMultiplier::from_value_per_gas(100),
228 }
229 }
230
231 pub fn exit(inheritor_id: ActorId) -> ! {
232 panic!("Program exited with inheritor id: {}", inheritor_id);
233 }
234
235 pub fn panic(data: &[u8]) -> ! {
236 if data.starts_with(b"GM") && data.len() >= 16 {
237 let mut payload = &data[16..];
238 if let Ok(s) = <String as parity_scale_codec::Decode>::decode(&mut payload) {
239 panic!("{}", s);
240 }
241 }
242 panic!("{:?}", data);
243 }
244
245 #[cfg(not(feature = "ethexe"))]
246 pub fn system_reserve_gas(_amount: GasUnit) -> Result<(), ::gcore::errors::Error> {
247 Ok(())
248 }
249 }
250};