multiversx_chain_vm/host/vm_hooks/vh_handler/
vh_call_value.rs1use crate::{
2 host::{
3 context::TxTokenTransfer,
4 vm_hooks::{vh_early_exit::early_exit_vm_error, VMHooksContext},
5 },
6 types::RawHandle,
7 vm_err_msg,
8};
9use multiversx_chain_core::EGLD_000000_TOKEN_IDENTIFIER;
10use multiversx_chain_vm_executor::VMHooksEarlyExit;
11use num_traits::Zero;
12
13use super::VMHooksHandler;
14
15impl<C: VMHooksContext> VMHooksHandler<C> {
16 pub fn check_not_payable(&mut self) -> Result<(), VMHooksEarlyExit> {
17 self.use_gas(self.gas_schedule().base_ops_api_cost.get_call_value)?;
18
19 if self.context.input_ref().egld_value > num_bigint::BigUint::zero() {
20 return Err(early_exit_vm_error(vm_err_msg::NON_PAYABLE_FUNC_EGLD));
21 }
22 if self.esdt_num_transfers() > 0 {
23 return Err(early_exit_vm_error(vm_err_msg::NON_PAYABLE_FUNC_ESDT));
24 }
25 Ok(())
26 }
27
28 pub fn load_egld_value(&mut self, dest: RawHandle) -> Result<(), VMHooksEarlyExit> {
29 self.use_gas(self.gas_schedule().big_int_api_cost.big_int_set_int_64)?;
30
31 let value = self.context.input_ref().received_egld().clone();
32 self.context.m_types_lock().bi_overwrite(dest, value.into());
33
34 Ok(())
35 }
36
37 pub fn load_all_esdt_transfers(
38 &mut self,
39 dest_handle: RawHandle,
40 ) -> Result<(), VMHooksEarlyExit> {
41 let num_bytes_copied = self
42 .context
43 .m_types_lock()
44 .mb_set_vec_of_esdt_payments(dest_handle, self.context.input_ref().received_esdt());
45 self.use_gas_for_data_copy(num_bytes_copied)?;
46
47 Ok(())
48 }
49
50 pub fn load_all_transfers(&self, dest_handle: RawHandle) -> Result<(), VMHooksEarlyExit> {
51 let direct_egld_value = self.context.input_ref().received_egld().clone();
52 let transfers = if !direct_egld_value.is_zero() {
53 vec![TxTokenTransfer {
54 token_identifier: EGLD_000000_TOKEN_IDENTIFIER.as_bytes().to_vec(),
55 nonce: 0,
56 value: direct_egld_value,
57 }]
58 } else {
59 self.context.input_ref().received_esdt().to_owned()
60 };
61 self.context
62 .m_types_lock()
63 .mb_set_vec_of_esdt_payments(dest_handle, &transfers);
64 Ok(())
65 }
66
67 pub fn esdt_num_transfers(&mut self) -> usize {
68 self.context.input_ref().received_esdt().len()
69 }
70}