multiversx_chain_vm/host/vm_hooks/vh_handler/
vh_endpoint_arg.rs1use multiversx_chain_vm_executor::VMHooksEarlyExit;
2use num_bigint::{BigInt, BigUint};
3use num_traits::ToPrimitive;
4
5use crate::host::vm_hooks::vh_early_exit::early_exit_vm_error;
6use crate::host::vm_hooks::VMHooksContext;
7use crate::vm_err_msg;
8
9use crate::types::RawHandle;
10
11use super::VMHooksHandler;
12
13impl<C: VMHooksContext> VMHooksHandler<C> {
16 pub fn get_num_arguments(&mut self) -> Result<i32, VMHooksEarlyExit> {
17 Ok(self.context.input_ref().args.len() as i32)
18 }
19
20 pub fn get_argument_len(&mut self, arg_index: i32) -> Result<usize, VMHooksEarlyExit> {
21 let arg = self.context.input_ref().get_argument_vec_u8(arg_index);
22 Ok(arg.len())
23 }
24
25 pub fn load_argument_managed_buffer(
26 &mut self,
27 arg_index: i32,
28 dest: RawHandle,
29 ) -> Result<(), VMHooksEarlyExit> {
30 self.use_gas(
31 self.gas_schedule()
32 .managed_buffer_api_cost
33 .m_buffer_set_bytes,
34 )?;
35
36 let arg_bytes = self.context.input_ref().get_argument_vec_u8(arg_index);
37 self.context.m_types_lock().mb_set(dest, arg_bytes);
38
39 Ok(())
40 }
41
42 pub fn load_argument_big_int_unsigned(
43 &mut self,
44 arg_index: i32,
45 dest: RawHandle,
46 ) -> Result<(), VMHooksEarlyExit> {
47 self.use_gas(
48 self.gas_schedule()
49 .big_int_api_cost
50 .big_int_set_unsigned_bytes,
51 )?;
52
53 let arg_bytes = self.context.input_ref().get_argument_vec_u8(arg_index);
54 self.context
55 .m_types_lock()
56 .bi_set_unsigned_bytes(dest, &arg_bytes);
57
58 Ok(())
59 }
60
61 pub fn load_argument_big_int_signed(
62 &mut self,
63 arg_index: i32,
64 dest: RawHandle,
65 ) -> Result<(), VMHooksEarlyExit> {
66 self.use_gas(
67 self.gas_schedule()
68 .big_int_api_cost
69 .big_int_set_signed_bytes,
70 )?;
71
72 let arg_bytes = self.context.input_ref().get_argument_vec_u8(arg_index);
73 self.context
74 .m_types_lock()
75 .bi_set_signed_bytes(dest, &arg_bytes);
76
77 Ok(())
78 }
79
80 pub fn get_argument_i64(&mut self, arg_index: i32) -> Result<i64, VMHooksEarlyExit> {
81 let bytes = self.context.input_ref().get_argument_vec_u8(arg_index);
83 let bi = BigInt::from_signed_bytes_be(&bytes);
84 if let Some(v) = bi.to_i64() {
85 Ok(v)
86 } else {
87 Err(early_exit_vm_error(vm_err_msg::ARG_OUT_OF_RANGE))
88 }
89 }
90
91 pub fn get_argument_u64(&mut self, arg_index: i32) -> Result<u64, VMHooksEarlyExit> {
92 let bytes = self.context.input_ref().get_argument_vec_u8(arg_index);
94 let bu = BigUint::from_bytes_be(&bytes);
95 if let Some(v) = bu.to_u64() {
96 Ok(v)
97 } else {
98 Err(early_exit_vm_error(vm_err_msg::ARG_OUT_OF_RANGE))
99 }
100 }
101
102 pub fn load_callback_closure_buffer(
103 &mut self,
104 dest: RawHandle,
105 ) -> Result<(), VMHooksEarlyExit> {
106 let has_closure_data = self
107 .context
108 .input_ref()
109 .promise_callback_closure_data
110 .is_some();
111
112 if has_closure_data {
113 self.use_gas(
114 self.gas_schedule()
115 .managed_buffer_api_cost
116 .m_buffer_set_bytes,
117 )?;
118
119 let closure_data = self
120 .context
121 .input_ref()
122 .promise_callback_closure_data
123 .clone()
124 .unwrap();
125
126 self.context.m_types_lock().mb_set(dest, closure_data);
127 Ok(())
128 } else {
129 Err(early_exit_vm_error(vm_err_msg::ERROR_NO_CALLBACK_CLOSURE))
130 }
131 }
132}