diff --git a/framework/base/src/api/managed_types.rs b/framework/base/src/api/managed_types.rs
index 3562020b95..1322ede5ee 100644
--- a/framework/base/src/api/managed_types.rs
+++ b/framework/base/src/api/managed_types.rs
@@ -8,6 +8,7 @@ mod managed_map_api;
mod managed_type_api;
mod managed_type_api_impl;
mod static_var_api;
+mod static_var_api_flags;
mod token_identifier_util;
pub use big_float_api::*;
@@ -19,3 +20,4 @@ pub use managed_map_api::*;
pub use managed_type_api::*;
pub use managed_type_api_impl::*;
pub use static_var_api::*;
+pub use static_var_api_flags::StaticVarApiFlags;
diff --git a/framework/base/src/api/managed_types/static_var_api.rs b/framework/base/src/api/managed_types/static_var_api.rs
index 8eaf474ef3..9044cd6b06 100644
--- a/framework/base/src/api/managed_types/static_var_api.rs
+++ b/framework/base/src/api/managed_types/static_var_api.rs
@@ -1,6 +1,6 @@
use crate::types::LockableStaticBuffer;
-use super::RawHandle;
+use super::{RawHandle, StaticVarApiFlags};
pub trait StaticVarApi {
type StaticVarApiImpl: StaticVarApiImpl;
@@ -24,13 +24,21 @@ pub trait StaticVarApiImpl {
fn get_num_arguments(&self) -> i32;
- fn set_call_value_egld_handle(&self, handle: RawHandle);
-
- fn get_call_value_egld_handle(&self) -> RawHandle;
-
- fn set_call_value_multi_esdt_handle(&self, handle: RawHandle);
-
- fn get_call_value_multi_esdt_handle(&self) -> RawHandle;
+ fn set_flags(&self, flags: StaticVarApiFlags);
+
+ fn get_flags(&self) -> StaticVarApiFlags;
+
+ /// Returns true if the flag is set, false if is default (false).
+ ///
+ /// If the flag is unset (false), will set it.
+ fn flag_is_set_or_update(&self, flag: StaticVarApiFlags) -> bool {
+ let mut current_flags = self.get_flags();
+ let contains_flag = current_flags.check_and_set(flag);
+ if !contains_flag {
+ self.set_flags(current_flags);
+ }
+ contains_flag
+ }
fn is_scaling_factor_cached(&self, decimals: usize) -> bool;
diff --git a/framework/base/src/api/managed_types/static_var_api_flags.rs b/framework/base/src/api/managed_types/static_var_api_flags.rs
new file mode 100644
index 0000000000..1c9e153e69
--- /dev/null
+++ b/framework/base/src/api/managed_types/static_var_api_flags.rs
@@ -0,0 +1,53 @@
+use bitflags::bitflags;
+
+bitflags! {
+ #[derive(Clone, Copy, Debug, PartialEq, Eq)]
+ pub struct StaticVarApiFlags: u8 {
+ const NONE = 0b00000000;
+ const CALL_VALUE_EGLD_INITIALIZED = 0b00000001;
+ const CALL_VALUE_EGLD_MULTI_INITIALIZED = 0b00000010;
+ const CALL_VALUE_MULTI_ESDT_INITIALIZED = 0b00000100;
+ const CALL_VALUE_ALL_INITIALIZED = 0b00001000;
+ }
+}
+
+impl StaticVarApiFlags {
+ pub fn check_and_set(&mut self, other: StaticVarApiFlags) -> bool {
+ let contains_flag = self.contains(other);
+ if !contains_flag {
+ *self |= other;
+ }
+ contains_flag
+ }
+}
+
+#[cfg(test)]
+pub mod tests {
+ use super::StaticVarApiFlags;
+
+ #[test]
+ fn test_check_and_set() {
+ let mut current = StaticVarApiFlags::NONE;
+
+ assert!(current.check_and_set(StaticVarApiFlags::NONE));
+ assert_eq!(current, StaticVarApiFlags::NONE);
+
+ assert!(!current.check_and_set(StaticVarApiFlags::CALL_VALUE_EGLD_INITIALIZED));
+ assert_eq!(current, StaticVarApiFlags::CALL_VALUE_EGLD_INITIALIZED);
+ assert!(current.check_and_set(StaticVarApiFlags::CALL_VALUE_EGLD_INITIALIZED));
+ assert_eq!(current, StaticVarApiFlags::CALL_VALUE_EGLD_INITIALIZED);
+
+ assert!(!current.check_and_set(StaticVarApiFlags::CALL_VALUE_ALL_INITIALIZED));
+ assert_eq!(
+ current,
+ StaticVarApiFlags::CALL_VALUE_EGLD_INITIALIZED
+ | StaticVarApiFlags::CALL_VALUE_ALL_INITIALIZED
+ );
+ assert!(current.check_and_set(StaticVarApiFlags::CALL_VALUE_ALL_INITIALIZED));
+ assert_eq!(
+ current,
+ StaticVarApiFlags::CALL_VALUE_EGLD_INITIALIZED
+ | StaticVarApiFlags::CALL_VALUE_ALL_INITIALIZED
+ );
+ }
+}
diff --git a/framework/base/src/api/uncallable/static_var_api_uncallable.rs b/framework/base/src/api/uncallable/static_var_api_uncallable.rs
index 1da3c772cf..005a302e53 100644
--- a/framework/base/src/api/uncallable/static_var_api_uncallable.rs
+++ b/framework/base/src/api/uncallable/static_var_api_uncallable.rs
@@ -1,5 +1,5 @@
use crate::{
- api::{RawHandle, StaticVarApi, StaticVarApiImpl},
+ api::{RawHandle, StaticVarApi, StaticVarApiFlags, StaticVarApiImpl},
types::LockableStaticBuffer,
};
@@ -41,19 +41,11 @@ impl StaticVarApiImpl for UncallableApi {
unreachable!()
}
- fn set_call_value_egld_handle(&self, _handle: RawHandle) {
+ fn set_flags(&self, _flags: StaticVarApiFlags) {
unreachable!()
}
- fn get_call_value_egld_handle(&self) -> RawHandle {
- unreachable!()
- }
-
- fn set_call_value_multi_esdt_handle(&self, _handle: RawHandle) {
- unreachable!()
- }
-
- fn get_call_value_multi_esdt_handle(&self) -> RawHandle {
+ fn get_flags(&self) -> StaticVarApiFlags {
unreachable!()
}
diff --git a/framework/base/src/contract_base/wrappers/call_value_wrapper.rs b/framework/base/src/contract_base/wrappers/call_value_wrapper.rs
index 3fb85e1658..1edb635a9d 100644
--- a/framework/base/src/contract_base/wrappers/call_value_wrapper.rs
+++ b/framework/base/src/contract_base/wrappers/call_value_wrapper.rs
@@ -3,7 +3,7 @@ use core::marker::PhantomData;
use crate::{
api::{
const_handles, use_raw_handle, CallValueApi, CallValueApiImpl, ErrorApi, ErrorApiImpl,
- HandleConstraints, ManagedTypeApi, StaticVarApiImpl,
+ ManagedTypeApi, StaticVarApiFlags, StaticVarApiImpl,
},
err_msg,
types::{
@@ -34,11 +34,10 @@ where
/// Retrieves the EGLD call value from the VM.
/// Will return 0 in case of an ESDT transfer (cannot have both EGLD and ESDT transfer simultaneously).
pub fn egld_value(&self) -> ManagedRef<'static, A, BigUint> {
- let mut call_value_handle: A::BigIntHandle =
- use_raw_handle(A::static_var_api_impl().get_call_value_egld_handle());
- if call_value_handle == const_handles::UNINITIALIZED_HANDLE {
- call_value_handle = use_raw_handle(const_handles::CALL_VALUE_EGLD);
- A::static_var_api_impl().set_call_value_egld_handle(call_value_handle.get_raw_handle());
+ let call_value_handle: A::BigIntHandle = use_raw_handle(const_handles::CALL_VALUE_EGLD);
+ if !A::static_var_api_impl()
+ .flag_is_set_or_update(StaticVarApiFlags::CALL_VALUE_EGLD_INITIALIZED)
+ {
A::call_value_api_impl().load_egld_value(call_value_handle.clone());
}
unsafe { ManagedRef::wrap_handle(call_value_handle) }
@@ -55,12 +54,11 @@ where
/// Will return 0 results if nothing was transfered, or just EGLD.
/// Fully managed underlying types, very efficient.
pub fn all_esdt_transfers(&self) -> ManagedRef<'static, A, ManagedVec>> {
- let mut call_value_handle: A::ManagedBufferHandle =
- use_raw_handle(A::static_var_api_impl().get_call_value_multi_esdt_handle());
- if call_value_handle == const_handles::UNINITIALIZED_HANDLE {
- call_value_handle = use_raw_handle(const_handles::CALL_VALUE_MULTI_ESDT);
- A::static_var_api_impl()
- .set_call_value_multi_esdt_handle(call_value_handle.get_raw_handle());
+ let call_value_handle: A::ManagedBufferHandle =
+ use_raw_handle(const_handles::CALL_VALUE_MULTI_ESDT);
+ if !A::static_var_api_impl()
+ .flag_is_set_or_update(StaticVarApiFlags::CALL_VALUE_MULTI_ESDT_INITIALIZED)
+ {
A::call_value_api_impl().load_all_esdt_transfers(call_value_handle.clone());
}
unsafe { ManagedRef::wrap_handle(call_value_handle) }
diff --git a/framework/scenario/src/api/local_api_vh/static_var_api_vh.rs b/framework/scenario/src/api/local_api_vh/static_var_api_vh.rs
index e72ae45f74..903094279e 100644
--- a/framework/scenario/src/api/local_api_vh/static_var_api_vh.rs
+++ b/framework/scenario/src/api/local_api_vh/static_var_api_vh.rs
@@ -1,6 +1,6 @@
use crate::api::{VMHooksApi, VMHooksApiBackend};
use multiversx_sc::{
- api::{use_raw_handle, RawHandle, StaticVarApi, StaticVarApiImpl},
+ api::{RawHandle, StaticVarApi, StaticVarApiFlags, StaticVarApiImpl},
types::LockableStaticBuffer,
};
@@ -55,30 +55,14 @@ impl StaticVarApiImpl for VMHooksApi {
self.with_static_data(|data| data.static_vars_cell.borrow().num_arguments)
}
- fn set_call_value_egld_handle(&self, handle: RawHandle) {
+ fn set_flags(&self, flags: StaticVarApiFlags) {
self.with_static_data(|data| {
- data.static_vars_cell.borrow_mut().call_value_egld_handle = handle;
+ data.static_vars_cell.borrow_mut().flags = flags;
})
}
- fn get_call_value_egld_handle(&self) -> RawHandle {
- self.with_static_data(|data| {
- use_raw_handle(data.static_vars_cell.borrow().call_value_egld_handle)
- })
- }
-
- fn set_call_value_multi_esdt_handle(&self, handle: RawHandle) {
- self.with_static_data(|data| {
- data.static_vars_cell
- .borrow_mut()
- .call_value_multi_esdt_handle = handle;
- })
- }
-
- fn get_call_value_multi_esdt_handle(&self) -> RawHandle {
- self.with_static_data(|data| {
- use_raw_handle(data.static_vars_cell.borrow().call_value_multi_esdt_handle)
- })
+ fn get_flags(&self) -> StaticVarApiFlags {
+ self.with_static_data(|data| data.static_vars_cell.borrow().flags)
}
fn is_scaling_factor_cached(&self, decimals: usize) -> bool {
diff --git a/framework/scenario/src/debug_executor/tx_static_vars.rs b/framework/scenario/src/debug_executor/tx_static_vars.rs
index 88277694c4..3468d14da6 100644
--- a/framework/scenario/src/debug_executor/tx_static_vars.rs
+++ b/framework/scenario/src/debug_executor/tx_static_vars.rs
@@ -1,13 +1,13 @@
-use multiversx_sc::api::{const_handles, RawHandle};
+use multiversx_sc::api::{const_handles, RawHandle, StaticVarApiFlags};
#[derive(Debug)]
pub struct TxStaticVars {
pub external_view_target_address_handle: RawHandle,
pub next_handle: RawHandle,
pub num_arguments: i32,
- pub call_value_egld_handle: RawHandle,
- pub call_value_multi_esdt_handle: RawHandle,
- //vec of true/false, true if bit from handle = scaling_start + index is not empty
+ pub flags: StaticVarApiFlags,
+
+ /// Vec of true/false, true if bit from handle = scaling_start + index is not empty
pub scaling_factor_init: [bool; const_handles::SCALING_FACTOR_LENGTH],
}
@@ -17,9 +17,8 @@ impl Default for TxStaticVars {
external_view_target_address_handle: 0,
next_handle: const_handles::NEW_HANDLE_START_FROM,
num_arguments: -1,
- call_value_egld_handle: const_handles::UNINITIALIZED_HANDLE,
- call_value_multi_esdt_handle: const_handles::UNINITIALIZED_HANDLE,
scaling_factor_init: [false; const_handles::SCALING_FACTOR_LENGTH],
+ flags: StaticVarApiFlags::NONE,
}
}
}
diff --git a/framework/wasm-adapter/src/api/managed_types/static_var_api_node.rs b/framework/wasm-adapter/src/api/managed_types/static_var_api_node.rs
index 501d53d68f..3c6b19996f 100644
--- a/framework/wasm-adapter/src/api/managed_types/static_var_api_node.rs
+++ b/framework/wasm-adapter/src/api/managed_types/static_var_api_node.rs
@@ -1,5 +1,5 @@
use multiversx_sc::{
- api::{const_handles, RawHandle, StaticVarApi, StaticVarApiImpl},
+ api::{const_handles, RawHandle, StaticVarApi, StaticVarApiFlags, StaticVarApiImpl},
types::LockableStaticBuffer,
};
@@ -9,8 +9,7 @@ static mut STATIC_BUFFER: LockableStaticBuffer = LockableStaticBuffer::new();
static mut EXTERNAL_VIEW_TARGET_ADDRESS_HANDLE: i32 = 0;
static mut NEXT_HANDLE: i32 = const_handles::NEW_HANDLE_START_FROM;
static mut NUM_ARGUMENTS: i32 = 0;
-static mut CALL_VALUE_EGLD_HANDLE: i32 = const_handles::UNINITIALIZED_HANDLE;
-static mut CALL_VALUE_MULTI_ESDT_HANDLE: i32 = const_handles::UNINITIALIZED_HANDLE;
+static mut FLAGS: StaticVarApiFlags = StaticVarApiFlags::NONE;
static mut SCALING_FACTOR_INIT: [bool; const_handles::SCALING_FACTOR_LENGTH] =
[false; const_handles::SCALING_FACTOR_LENGTH];
@@ -62,24 +61,14 @@ impl StaticVarApiImpl for VmApiImpl {
unsafe { NUM_ARGUMENTS }
}
- fn set_call_value_egld_handle(&self, handle: RawHandle) {
+ fn set_flags(&self, flags: StaticVarApiFlags) {
unsafe {
- CALL_VALUE_EGLD_HANDLE = handle;
+ FLAGS = flags;
}
}
- fn get_call_value_egld_handle(&self) -> RawHandle {
- unsafe { CALL_VALUE_EGLD_HANDLE }
- }
-
- fn set_call_value_multi_esdt_handle(&self, handle: RawHandle) {
- unsafe {
- CALL_VALUE_MULTI_ESDT_HANDLE = handle;
- }
- }
-
- fn get_call_value_multi_esdt_handle(&self) -> RawHandle {
- unsafe { CALL_VALUE_MULTI_ESDT_HANDLE }
+ fn get_flags(&self) -> StaticVarApiFlags {
+ unsafe { FLAGS }
}
fn is_scaling_factor_cached(&self, decimals: usize) -> bool {