multiversx_sc_scenario/api/impl_vh/
static_api.rs

1use multiversx_chain_vm::{executor::VMHooks, host::vm_hooks::VMHooksDispatcher};
2use multiversx_chain_vm_executor::VMHooksEarlyExit;
3use multiversx_sc::{api::RawHandle, types::Address};
4use std::sync::Mutex;
5
6use crate::executor::debug::{ContractDebugInstanceState, StaticVarData};
7
8use super::{StaticApiVMHooksContext, VMHooksApi, VMHooksApiBackend};
9
10fn new_static_api_vh() -> VMHooksDispatcher<StaticApiVMHooksContext> {
11    VMHooksDispatcher::new(StaticApiVMHooksContext::default())
12}
13
14thread_local! {
15    static STATIC_API_VH_CELL: Mutex<VMHooksDispatcher<StaticApiVMHooksContext>> = Mutex::new(new_static_api_vh());
16
17    static STATIC_API_STATIC_CELL: Mutex<StaticVarData> = Mutex::new(StaticVarData::default());
18}
19
20#[derive(Clone)]
21pub struct StaticApiBackend;
22
23impl VMHooksApiBackend for StaticApiBackend {
24    type HandleType = RawHandle;
25
26    fn with_vm_hooks<R, F>(f: F) -> R
27    where
28        F: FnOnce(&mut dyn VMHooks) -> Result<R, VMHooksEarlyExit>,
29    {
30        STATIC_API_VH_CELL.with(|vh_mutex| {
31            let mut vh = vh_mutex.lock().unwrap();
32            f(&mut *vh).unwrap_or_else(|err| ContractDebugInstanceState::early_exit_panic(err))
33        })
34    }
35
36    fn with_static_data<R, F>(f: F) -> R
37    where
38        F: FnOnce(&StaticVarData) -> R,
39    {
40        STATIC_API_STATIC_CELL.with(|data_mutex| {
41            let data = data_mutex.lock().unwrap();
42            f(&data)
43        })
44    }
45}
46
47pub type StaticApi = VMHooksApi<StaticApiBackend>;
48
49impl StaticApi {
50    /// The static API does not allow interrogating the Tx input,
51    /// but does offer a placeholder for the current ("SC") address, to help with contract calls.
52    ///
53    /// This placeholder then needs to be converted to something useful.
54    pub fn is_current_address_placeholder(address: &Address) -> bool {
55        address == &StaticApiVMHooksContext::CURRENT_ADDRESS_PLACEHOLDER
56    }
57
58    pub fn reset() {
59        STATIC_API_VH_CELL.with(|vh_mutex| {
60            let mut vh = vh_mutex.lock().unwrap();
61            *vh = new_static_api_vh()
62        });
63
64        STATIC_API_STATIC_CELL.with(|data_mutex| {
65            let mut data = data_mutex.lock().unwrap();
66            *data = StaticVarData::default()
67        })
68    }
69}
70
71impl std::fmt::Debug for StaticApi {
72    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
73        f.debug_struct("StaticApi").finish()
74    }
75}