1use wasmer::{imports, Function, ImportObject, Store};
11
12use super::MethodCallError;
13
14pub trait ContractBinaryInterface<T>
25where
26 T: wasmer::WasmerEnv + 'static,
27{
28 fn set(
30 env: &T,
31 key_ptr: u32,
32 key_len: u32,
33 value_ptr: u32,
34 value_len: u32,
35 ) -> Result<(), FuncError>;
36
37 fn get(env: &T, key_ptr: u32, key_len: u32, value_ptr_ptr: u32) -> Result<i64, FuncError>;
40
41 fn get_network_storage(
44 env: &T,
45 key_ptr: u32,
46 key_len: u32,
47 value_ptr_ptr: u32,
48 ) -> Result<i64, FuncError>;
49
50 fn balance(env: &T) -> Result<u64, FuncError>;
52
53 fn block_height(env: &T) -> Result<u64, FuncError>;
55
56 fn block_timestamp(env: &T) -> Result<u32, FuncError>;
58
59 fn prev_block_hash(env: &T, hash_ptr_ptr: u32) -> Result<(), FuncError>;
62
63 fn calling_account(env: &T, address_ptr_ptr: u32) -> Result<(), FuncError>;
68
69 fn current_account(env: &T, address_ptr_ptr: u32) -> Result<(), FuncError>;
73
74 fn method(env: &T, method_ptr_ptr: u32) -> Result<u32, FuncError>;
78
79 fn arguments(env: &T, arguments_ptr_ptr: u32) -> Result<u32, FuncError>;
83
84 fn amount(env: &T) -> Result<u64, FuncError>;
87
88 fn is_internal_call(env: &T) -> Result<i32, FuncError>;
90
91 fn transaction_hash(env: &T, hash_ptr_ptr: u32) -> Result<(), FuncError>;
94
95 fn call(
100 env: &T,
101 call_input_ptr: u32,
102 call_input_len: u32,
103 rval_ptr_ptr: u32,
104 ) -> Result<u32, FuncError>;
105
106 fn return_value(env: &T, value_ptr: u32, value_len: u32) -> Result<(), FuncError>;
109
110 fn transfer(env: &T, transfer_input_ptr: u32) -> Result<(), FuncError>;
113
114 fn defer_create_deposit(
117 env: &T,
118 create_deposit_input_ptr: u32,
119 create_deposit_input_len: u32,
120 ) -> Result<(), FuncError>;
121
122 fn defer_set_deposit_settings(
125 env: &T,
126 set_deposit_settings_input_ptr: u32,
127 set_deposit_settings_input_len: u32,
128 ) -> Result<(), FuncError>;
129
130 fn defer_topup_deposit(
133 env: &T,
134 top_up_deposit_input_ptr: u32,
135 top_up_deposit_input_len: u32,
136 ) -> Result<(), FuncError>;
137
138 fn defer_withdraw_deposit(
141 env: &T,
142 withdraw_deposit_input_ptr: u32,
143 withdraw_deposit_input_len: u32,
144 ) -> Result<(), FuncError>;
145
146 fn defer_stake_deposit(
149 env: &T,
150 stake_deposit_input_ptr: u32,
151 stake_deposit_input_len: u32,
152 ) -> Result<(), FuncError>;
153
154 fn defer_unstake_deposit(
157 env: &T,
158 unstake_deposit_input_ptr: u32,
159 unstake_deposit_input_len: u32,
160 ) -> Result<(), FuncError>;
161
162 fn log(env: &T, log_ptr: u32, log_len: u32) -> Result<(), FuncError>;
164
165 fn sha256(env: &T, msg_ptr: u32, msg_len: u32, digest_ptr_ptr: u32) -> Result<(), FuncError>;
168
169 fn keccak256(env: &T, msg_ptr: u32, msg_len: u32, digest_ptr_ptr: u32)
172 -> Result<(), FuncError>;
173
174 fn ripemd(env: &T, msg_ptr: u32, msg_len: u32, digest_ptr_ptr: u32) -> Result<(), FuncError>;
177
178 fn verify_ed25519_signature(
180 env: &T,
181 msg_ptr: u32,
182 msg_len: u32,
183 signature_ptr: u32,
184 address_ptr: u32,
185 ) -> Result<i32, FuncError>;
186}
187
188pub(crate) fn create_importable<'a, T, K>(store: &'a Store, env: &T) -> Importable<'a>
190where
191 T: wasmer::WasmerEnv + 'static,
192 K: ContractBinaryInterface<T> + 'static,
193{
194 Importable(
195 imports! {
196 "env" => {
197 "set" => Function::new_native_with_env(store, env.clone(), K::set),
198 "get" => Function::new_native_with_env(store, env.clone(), K::get),
199 "get_network_storage" => Function::new_native_with_env(store, env.clone(), K::get_network_storage),
200 "balance" => Function::new_native_with_env(store, env.clone(), K::balance),
201
202 "block_height" => Function::new_native_with_env(store, env.clone(), K::block_height),
203 "block_timestamp" => Function::new_native_with_env(store, env.clone(), K::block_timestamp),
204 "prev_block_hash" => Function::new_native_with_env(store, env.clone(), K::prev_block_hash),
205
206 "calling_account" => Function::new_native_with_env(store, env.clone(), K::calling_account),
207 "current_account" => Function::new_native_with_env(store, env.clone(), K::current_account),
208 "method" => Function::new_native_with_env(store, env.clone(), K::method),
209 "arguments" => Function::new_native_with_env(store, env.clone(), K::arguments),
210 "amount" => Function::new_native_with_env(store, env.clone(), K::amount),
211 "is_internal_call" => Function::new_native_with_env(store, env.clone(), K::is_internal_call),
212 "transaction_hash" => Function::new_native_with_env(store, env.clone(), K::transaction_hash),
213
214 "call" => Function::new_native_with_env(store, env.clone(), K::call),
215 "return_value" => Function::new_native_with_env(store, env.clone(), K::return_value),
216 "transfer" => Function::new_native_with_env(store, env.clone(), K::transfer),
217 "defer_create_deposit" => Function::new_native_with_env(store, env.clone(), K::defer_create_deposit),
218 "defer_set_deposit_settings" => Function::new_native_with_env(store, env.clone(), K::defer_set_deposit_settings),
219 "defer_topup_deposit" => Function::new_native_with_env(store, env.clone(), K::defer_topup_deposit),
220 "defer_withdraw_deposit" => Function::new_native_with_env(store, env.clone(), K::defer_withdraw_deposit),
221 "defer_stake_deposit" => Function::new_native_with_env(store, env.clone(), K::defer_stake_deposit),
222 "defer_unstake_deposit" => Function::new_native_with_env(store, env.clone(), K::defer_unstake_deposit),
223
224 "_log" => Function::new_native_with_env(store, env.clone(), K::log),
225
226 "sha256" => Function::new_native_with_env(store, env.clone(), K::sha256),
227 "keccak256" => Function::new_native_with_env(store, env.clone(), K::keccak256),
228 "ripemd" => Function::new_native_with_env(store, env.clone(), K::ripemd),
229 "verify_ed25519_signature" => Function::new_native_with_env(store, env.clone(), K::verify_ed25519_signature),
230 }
231 },
232 store,
233 )
234}
235
236pub(crate) fn create_importable_view<'a, T, K>(store: &'a Store, env: &T) -> Importable<'a>
238where
239 T: wasmer::WasmerEnv + 'static,
240 K: ContractBinaryInterface<T> + 'static,
241{
242 Importable(
243 imports! {
244 "env" => {
245 "set" => Function::new_native(store, not_callable::set),
246 "get" => Function::new_native_with_env(store, env.clone(), K::get),
247 "get_network_storage" => Function::new_native_with_env(store, env.clone(), K::get_network_storage),
248 "balance" => Function::new_native_with_env(store, env.clone(), K::balance),
249
250 "block_height" => Function::new_native(store, not_callable::block_height),
251 "block_timestamp" => Function::new_native(store, not_callable::block_timestamp),
252 "prev_block_hash" => Function::new_native(store, not_callable::prev_block_hash),
253
254 "calling_account" => Function::new_native(store, not_callable::calling_account),
255 "current_account" => Function::new_native_with_env(store, env.clone(), K::current_account),
256 "method" => Function::new_native_with_env(store, env.clone(), K::method),
257 "arguments" => Function::new_native_with_env(store, env.clone(), K::arguments),
258 "amount" => Function::new_native(store, not_callable::amount),
259 "is_internal_call" => Function::new_native_with_env(store, env.clone(), K::is_internal_call),
260 "transaction_hash" => Function::new_native(store, not_callable::transaction_hash),
261
262 "call" => Function::new_native_with_env(store, env.clone(), K::call), "return_value" => Function::new_native_with_env(store, env.clone(), K::return_value),
264 "transfer" => Function::new_native(store, not_callable::transfer),
265 "defer_create_deposit" => Function::new_native(store, not_callable::defer_create_deposit),
266 "defer_set_deposit_settings" => Function::new_native(store, not_callable::defer_set_deposit_settings),
267 "defer_topup_deposit" => Function::new_native(store, not_callable::defer_topup_deposit),
268 "defer_withdraw_deposit" => Function::new_native(store, not_callable::defer_withdraw_deposit),
269 "defer_stake_deposit" => Function::new_native(store, not_callable::defer_stake_deposit),
270 "defer_unstake_deposit" => Function::new_native(store, not_callable::defer_unstake_deposit),
271
272 "_log" => Function::new_native_with_env(store, env.clone(), K::log),
273
274 "sha256" => Function::new_native_with_env(store, env.clone(), K::sha256),
275 "keccak256" => Function::new_native_with_env(store, env.clone(), K::keccak256),
276 "ripemd" => Function::new_native_with_env(store, env.clone(), K::ripemd),
277 "verify_ed25519_signature" => Function::new_native_with_env(store, env.clone(), K::verify_ed25519_signature),
278 }
279 },
280 store,
281 )
282}
283
284pub(crate) struct Importable<'a>(pub(crate) ImportObject, &'a Store);
286
287pub(crate) mod blank {
290 use wasmer::{imports, Function, Store};
291
292 pub(crate) fn imports(store: &Store) -> wasmer::ImportObject {
293 imports! {
294 "env" => {
295 "set" => Function::new_native(store, set),
296 "get" => Function::new_native(store, get),
297 "get_network_storage" => Function::new_native(store, get_network_storage),
298 "balance" => Function::new_native(store, balance),
299
300 "block_height" => Function::new_native(store, block_height),
301 "block_timestamp" => Function::new_native(store, block_timestamp),
302 "prev_block_hash" => Function::new_native(store, prev_block_hash),
303
304 "calling_account" => Function::new_native(store, calling_account),
305 "current_account" => Function::new_native(store, current_account),
306 "method" => Function::new_native(store, method),
307 "arguments" => Function::new_native(store, arguments),
308 "amount" => Function::new_native(store, amount),
309 "is_internal_call" => Function::new_native(store, is_internal_call),
310 "transaction_hash" => Function::new_native(store, transaction_hash),
311
312 "call" => Function::new_native(store, call),
313 "return_value" => Function::new_native(store, return_value),
314 "transfer" => Function::new_native(store, transfer),
315 "defer_create_deposit" => Function::new_native(store, defer_create_deposit),
316 "defer_set_deposit_settings" => Function::new_native(store, defer_set_deposit_settings),
317 "defer_topup_deposit" => Function::new_native(store, defer_topup_deposit),
318 "defer_withdraw_deposit" => Function::new_native(store, defer_withdraw_deposit),
319 "defer_stake_deposit" => Function::new_native(store, defer_stake_deposit),
320 "defer_unstake_deposit" => Function::new_native(store, defer_unstake_deposit),
321
322 "_log" => Function::new_native(store, log),
323
324 "sha256" => Function::new_native(store, sha256),
325 "keccak256" => Function::new_native(store, keccak256),
326 "ripemd" => Function::new_native(store, ripemd),
327 "verify_ed25519_signature" => Function::new_native(store, verify_ed25519_signature),
328 }
329 }
330 }
331
332 pub(crate) fn set(_: u32, _: u32, _: u32, _: u32) {}
333 pub(crate) fn get(_: u32, _: u32, _: u32) -> i64 {
334 0
335 }
336 pub(crate) fn get_network_storage(_: u32, _: u32, _: u32) -> i64 {
337 0
338 }
339 pub(crate) fn balance() -> u64 {
340 0
341 }
342
343 pub(crate) fn block_height() -> u64 {
344 0
345 }
346 pub(crate) fn block_timestamp() -> u32 {
347 0
348 }
349 pub(crate) fn prev_block_hash(_: u32) {}
350
351 pub(crate) fn calling_account(_: u32) {}
352 pub(crate) fn current_account(_: u32) {}
353 pub(crate) fn method(_: u32) -> u32 {
354 0
355 }
356 pub(crate) fn arguments(_: u32) -> u32 {
357 0
358 }
359 pub(crate) fn amount() -> u64 {
360 0
361 }
362 pub(crate) fn is_internal_call() -> i32 {
363 0
364 }
365 pub(crate) fn transaction_hash(_: u32) {}
366
367 pub(crate) fn call(_: u32, _: u32, _: u32) -> u32 {
368 0
369 }
370 pub(crate) fn return_value(_: u32, _: u32) {}
371 pub(crate) fn transfer(_: u32) {}
372 pub(crate) fn defer_create_deposit(_: u32, _: u32) {}
373 pub(crate) fn defer_set_deposit_settings(_: u32, _: u32) {}
374 pub(crate) fn defer_topup_deposit(_: u32, _: u32) {}
375 pub(crate) fn defer_withdraw_deposit(_: u32, _: u32) {}
376 pub(crate) fn defer_stake_deposit(_: u32, _: u32) {}
377 pub(crate) fn defer_unstake_deposit(_: u32, _: u32) {}
378
379 pub(crate) fn log(_: u32, _: u32) {}
380
381 pub(crate) fn sha256(_: u32, _: u32, _: u32) {}
382 pub(crate) fn keccak256(_: u32, _: u32, _: u32) {}
383 pub(crate) fn ripemd(_: u32, _: u32, _: u32) {}
384 pub(crate) fn verify_ed25519_signature(_: u32, _: u32, _: u32, _: u32) -> i32 {
385 0
386 }
387}
388
389mod not_callable {
391 use super::FuncError;
392
393 pub(crate) fn set(_: u32, _: u32, _: u32, _: u32) -> Result<(), FuncError> {
394 Err(FuncError::Internal)
395 }
396
397 pub(crate) fn block_height() -> Result<u64, FuncError> {
398 Err(FuncError::Internal)
399 }
400 pub(crate) fn block_timestamp() -> Result<u32, FuncError> {
401 Err(FuncError::Internal)
402 }
403 pub(crate) fn prev_block_hash(_: u32) -> Result<(), FuncError> {
404 Err(FuncError::Internal)
405 }
406
407 pub(crate) fn calling_account(_: u32) -> Result<(), FuncError> {
408 Err(FuncError::Internal)
409 }
410 pub(crate) fn amount() -> Result<u64, FuncError> {
411 Err(FuncError::Internal)
412 }
413 pub(crate) fn transaction_hash(_: u32) -> Result<(), FuncError> {
414 Err(FuncError::Internal)
415 }
416
417 pub(crate) fn transfer(_: u32) -> Result<(), FuncError> {
418 Err(FuncError::Internal)
419 }
420 pub(crate) fn defer_create_deposit(_: u32, _: u32) -> Result<(), FuncError> {
421 Err(FuncError::Internal)
422 }
423 pub(crate) fn defer_set_deposit_settings(_: u32, _: u32) -> Result<(), FuncError> {
424 Err(FuncError::Internal)
425 }
426 pub(crate) fn defer_topup_deposit(_: u32, _: u32) -> Result<(), FuncError> {
427 Err(FuncError::Internal)
428 }
429 pub(crate) fn defer_withdraw_deposit(_: u32, _: u32) -> Result<(), FuncError> {
430 Err(FuncError::Internal)
431 }
432 pub(crate) fn defer_stake_deposit(_: u32, _: u32) -> Result<(), FuncError> {
433 Err(FuncError::Internal)
434 }
435 pub(crate) fn defer_unstake_deposit(_: u32, _: u32) -> Result<(), FuncError> {
436 Err(FuncError::Internal)
437 }
438}
439
440#[derive(Debug, thiserror::Error)]
442pub enum FuncError {
443 #[error("Internal")]
444 Internal,
445
446 #[error("Runtime")]
447 Runtime(anyhow::Error),
448
449 #[error("GasExhaustionError")]
450 GasExhaustionError,
451
452 #[error("Runtime")]
454 MethodCallError(MethodCallError),
455
456 #[error("ContractNotFound")]
458 ContractNotFound,
459
460 #[error("InsufficientBalance")]
461 InsufficientBalance,
462}
463
464impl From<wasmer::RuntimeError> for FuncError {
465 fn from(e: wasmer::RuntimeError) -> Self {
466 Self::Runtime(e.into())
467 }
468}
469
470impl From<anyhow::Error> for FuncError {
471 fn from(e: anyhow::Error) -> Self {
472 Self::Runtime(e)
473 }
474}