multiversx_chain_vm/host/vm_hooks/vh_handler/
vh_call_value.rs

1use 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}