multiversx_sc_scenario/scenario/run_vm/
sc_deploy.rs

1use crate::{
2    multiversx_sc::types::heap::Address, scenario::model::ScDeployStep, scenario_model::TxResponse,
3};
4
5use multiversx_chain_vm::{
6    host::{
7        context::{TxFunctionName, TxInput, TxResult},
8        execution,
9        runtime::{RuntimeInstanceCallLambda, RuntimeInstanceCallLambdaDefault},
10    },
11    types::VMCodeMetadata,
12};
13
14use super::{check_tx_output, tx_input_util::generate_tx_hash, ScenarioVMRunner};
15
16impl ScenarioVMRunner {
17    /// Adds a SC deploy step, as specified in the `step` argument, then executes it.
18    ///
19    /// The result of the operation gets saved back in the step's response field.
20    pub fn perform_sc_deploy_update_results(&mut self, step: &mut ScDeployStep) {
21        let (new_address, tx_result) =
22            self.perform_sc_deploy_lambda(step, RuntimeInstanceCallLambdaDefault);
23        if let Some(tx_expect) = &step.expect {
24            check_tx_output(&step.id, tx_expect, &tx_result);
25        }
26        let mut response = TxResponse::from_tx_result(tx_result);
27        response.new_deployed_address = Some(new_address);
28        step.save_response(response);
29    }
30
31    pub fn perform_sc_deploy_lambda<F>(
32        &mut self,
33        sc_deploy_step: &ScDeployStep,
34        f: F,
35    ) -> (Address, TxResult)
36    where
37        F: RuntimeInstanceCallLambda,
38    {
39        let tx_input = tx_input_from_deploy(sc_deploy_step, f.override_function_name());
40        let runtime = self.create_debugger_runtime();
41        let contract_code = &sc_deploy_step.tx.contract_code.value;
42        let (new_address, tx_result) = execution::commit_deploy(
43            tx_input,
44            contract_code,
45            VMCodeMetadata::from(sc_deploy_step.tx.code_metadata.bits()),
46            &mut self.blockchain_mock.state,
47            &runtime,
48            f,
49        );
50        assert!(
51            tx_result.pending_calls.no_calls(),
52            "Async calls from constructors are currently not supported"
53        );
54        (new_address, tx_result)
55    }
56}
57
58fn tx_input_from_deploy(
59    sc_deploy_step: &ScDeployStep,
60    override_func_name: Option<TxFunctionName>,
61) -> TxInput {
62    let tx = &sc_deploy_step.tx;
63    TxInput {
64        from: tx.from.to_address(),
65        to: multiversx_chain_vm::types::VMAddress::zero(),
66        egld_value: tx.egld_value.value.clone(),
67        esdt_values: Vec::new(),
68        func_name: override_func_name.unwrap_or(TxFunctionName::INIT),
69        args: tx
70            .arguments
71            .iter()
72            .map(|scen_arg| scen_arg.value.clone())
73            .collect(),
74        gas_limit: tx.gas_limit.value,
75        gas_price: tx.gas_price.value,
76        tx_hash: generate_tx_hash(&sc_deploy_step.id, &sc_deploy_step.explicit_tx_hash),
77        ..Default::default()
78    }
79}