diff --git a/framework/base/src/storage/storage_key.rs b/framework/base/src/storage/storage_key.rs index 5f3f0578c9..47520108a6 100644 --- a/framework/base/src/storage/storage_key.rs +++ b/framework/base/src/storage/storage_key.rs @@ -79,6 +79,15 @@ impl From> for StorageKey { } } +impl From<&str> for StorageKey { + #[inline] + fn from(s: &str) -> Self { + StorageKey { + buffer: ManagedBuffer::from(s), + } + } +} + impl From> for StorageKey where M: ManagedTypeApi + ErrorApi, diff --git a/framework/scenario/src/api/impl_vh/single_tx_api.rs b/framework/scenario/src/api/impl_vh/single_tx_api.rs index c1be18c53c..e57614a853 100644 --- a/framework/scenario/src/api/impl_vh/single_tx_api.rs +++ b/framework/scenario/src/api/impl_vh/single_tx_api.rs @@ -2,7 +2,9 @@ use std::cell::RefCell; use multiversx_chain_vm::{ executor::VMHooks, + types::VMAddress, vm_hooks::{SingleTxApiData, SingleTxApiVMHooksHandler, VMHooksDispatcher}, + world_mock::AccountData, }; use multiversx_sc::api::RawHandle; @@ -51,7 +53,7 @@ impl SingleTxApi { }) } - pub fn with_global(&mut self, f: F) -> R + pub fn with_global(f: F) -> R where F: FnOnce(&mut SingleTxApiData) -> R, { @@ -60,6 +62,13 @@ impl SingleTxApi { handler.with_mut_data(f) }) } + + pub fn with_global_default_account(f: F) -> R + where + F: FnOnce(&mut AccountData) -> R, + { + Self::with_global(|data| data.with_account_mut(&VMAddress::zero(), f)) + } } impl std::fmt::Debug for SingleTxApi { diff --git a/framework/scenario/tests/single_tx_api_test.rs b/framework/scenario/tests/single_tx_api_test.rs new file mode 100644 index 0000000000..24ce21cdd2 --- /dev/null +++ b/framework/scenario/tests/single_tx_api_test.rs @@ -0,0 +1,47 @@ +use multiversx_sc::contract_base::StorageRawWrapper; +use multiversx_sc_scenario::api::SingleTxApi; + +#[test] +fn single_tx_api_test() { + let storage_raw = StorageRawWrapper::::new(); + let storage_key = "test-num"; + + // unitialized, we get the default + let x: i32 = storage_raw.read(storage_key); + assert_eq!(x, 0); + + // write, as if from a contract + storage_raw.write(storage_key, &5i32); + let x: i32 = storage_raw.read(storage_key); + assert_eq!(x, 5); + + // check directly in storage + SingleTxApi::with_global_default_account(|account| { + let value = account.storage.get(storage_key.as_bytes()).unwrap(); + assert_eq!(value, &vec![5u8]); + + // change value directly in storage + account + .storage + .insert(storage_key.as_bytes().to_vec(), vec![7u8]); + }); + + // read again + let x: i32 = storage_raw.read(storage_key); + assert_eq!(x, 7); + + // clear everything, globally + SingleTxApi::clear_global(); + let x: i32 = storage_raw.read(storage_key); + assert_eq!(x, 0); + + // checking directly in storage + SingleTxApi::with_global_default_account(|account| { + let value = account + .storage + .get(storage_key.as_bytes()) + .cloned() + .unwrap_or_default(); + assert!(value.is_empty()); + }); +} diff --git a/vm/src/vm_hooks/vh_impl/vh_single_tx_api.rs b/vm/src/vm_hooks/vh_impl/vh_single_tx_api.rs index c6c32b52bd..97b523e1e5 100644 --- a/vm/src/vm_hooks/vh_impl/vh_single_tx_api.rs +++ b/vm/src/vm_hooks/vh_impl/vh_single_tx_api.rs @@ -26,6 +26,19 @@ pub struct SingleTxApiData { pub current_block_info: BlockInfo, } +impl SingleTxApiData { + pub fn with_account_mut(&self, address: &VMAddress, f: F) -> R + where + F: FnOnce(&mut AccountData) -> R, + { + let mut accounts = self.accounts.borrow_mut(); + let account = accounts + .entry(address.clone()) + .or_insert(AccountData::new_empty(address.clone())); + f(account) + } +} + #[derive(Default, Debug, Clone)] pub struct SingleTxApiVMHooksHandler(Rc); @@ -38,17 +51,6 @@ impl SingleTxApiVMHooksHandler { .expect("could not retrieve mutable reference to SingleTxApi data"); f(data) } - - fn with_account_mut(&self, address: &VMAddress, f: F) -> R - where - F: FnOnce(&mut AccountData) -> R, - { - let mut accounts = self.0.accounts.borrow_mut(); - let account = accounts - .entry(address.clone()) - .or_insert(AccountData::new_empty(address.clone())); - f(account) - } } impl VMHooksHandlerSource for SingleTxApiVMHooksHandler { @@ -77,13 +79,13 @@ impl VMHooksHandlerSource for SingleTxApiVMHooksHandler { } fn storage_read_any_address(&self, address: &VMAddress, key: &[u8]) -> Vec { - self.with_account_mut(address, |account| { + self.0.with_account_mut(address, |account| { account.storage.get(key).cloned().unwrap_or_default() }) } fn storage_write(&self, key: &[u8], value: &[u8]) { - self.with_account_mut(&self.0.tx_input_box.to, |account| { + self.0.with_account_mut(&self.0.tx_input_box.to, |account| { account.storage.insert(key.to_vec(), value.to_vec()); }); } @@ -97,7 +99,7 @@ impl VMHooksHandlerSource for SingleTxApiVMHooksHandler { } fn account_data(&self, address: &VMAddress) -> AccountData { - self.with_account_mut(address, |account| account.clone()) + self.0.with_account_mut(address, |account| account.clone()) } fn account_code(&self, _address: &VMAddress) -> Vec {