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..8fd007d648 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,6 +24,22 @@ pub trait StaticVarApiImpl {
fn get_num_arguments(&self) -> i32;
+ 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 set_call_value_egld_handle(&self, handle: RawHandle);
fn get_call_value_egld_handle(&self) -> RawHandle;
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..db126b337d 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,6 +41,14 @@ impl StaticVarApiImpl for UncallableApi {
unreachable!()
}
+ fn set_flags(&self, _flags: StaticVarApiFlags) {
+ unreachable!()
+ }
+
+ fn get_flags(&self) -> StaticVarApiFlags {
+ unreachable!()
+ }
+
fn set_call_value_egld_handle(&self, _handle: RawHandle) {
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..07bef47bda 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::{use_raw_handle, RawHandle, StaticVarApi, StaticVarApiFlags, StaticVarApiImpl},
types::LockableStaticBuffer,
};
@@ -55,6 +55,16 @@ impl StaticVarApiImpl for VMHooksApi {
self.with_static_data(|data| data.static_vars_cell.borrow().num_arguments)
}
+ fn set_flags(&self, flags: StaticVarApiFlags) {
+ self.with_static_data(|data| {
+ data.static_vars_cell.borrow_mut().flags = flags;
+ })
+ }
+
+ fn get_flags(&self) -> StaticVarApiFlags {
+ self.with_static_data(|data| data.static_vars_cell.borrow().flags)
+ }
+
fn set_call_value_egld_handle(&self, handle: RawHandle) {
self.with_static_data(|data| {
data.static_vars_cell.borrow_mut().call_value_egld_handle = handle;
diff --git a/framework/scenario/src/debug_executor/tx_static_vars.rs b/framework/scenario/src/debug_executor/tx_static_vars.rs
index 88277694c4..bca543d8ba 100644
--- a/framework/scenario/src/debug_executor/tx_static_vars.rs
+++ b/framework/scenario/src/debug_executor/tx_static_vars.rs
@@ -1,13 +1,15 @@
-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 flags: StaticVarApiFlags,
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
+
+ /// 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],
}
@@ -20,6 +22,7 @@ impl Default for TxStaticVars {
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..b282449c94 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,6 +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 FLAGS: StaticVarApiFlags = StaticVarApiFlags::NONE;
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 SCALING_FACTOR_INIT: [bool; const_handles::SCALING_FACTOR_LENGTH] =
@@ -62,6 +63,16 @@ impl StaticVarApiImpl for VmApiImpl {
unsafe { NUM_ARGUMENTS }
}
+ fn set_flags(&self, flags: StaticVarApiFlags) {
+ unsafe {
+ FLAGS = flags;
+ }
+ }
+
+ fn get_flags(&self) -> StaticVarApiFlags {
+ unsafe { FLAGS }
+ }
+
fn set_call_value_egld_handle(&self, handle: RawHandle) {
unsafe {
CALL_VALUE_EGLD_HANDLE = handle;