diff --git a/chain/vm/src/host/context/managed_type_container/handle_map.rs b/chain/vm/src/host/context/managed_type_container/handle_map.rs index f121389696..8390a425f2 100644 --- a/chain/vm/src/host/context/managed_type_container/handle_map.rs +++ b/chain/vm/src/host/context/managed_type_container/handle_map.rs @@ -49,6 +49,10 @@ impl HandleMap { } pub fn remove_handle(&mut self, handle: RawHandle) { + assert!( + self.map.contains_key(&handle), + "attempting to remove non-existing handle {handle}, this is a memory managedment issue" + ); let _ = self.map.remove(&handle); } } diff --git a/chain/vm/src/host/context/managed_type_container/tx_managed_buffer.rs b/chain/vm/src/host/context/managed_type_container/tx_managed_buffer.rs index 0fff43c1c4..cbab957225 100644 --- a/chain/vm/src/host/context/managed_type_container/tx_managed_buffer.rs +++ b/chain/vm/src/host/context/managed_type_container/tx_managed_buffer.rs @@ -185,6 +185,7 @@ impl ManagedTypeContainer { } pub fn mb_remove(&mut self, handle: RawHandle) { + println!("removing MB: {handle}"); self.managed_buffer_map.remove_handle(handle); } } diff --git a/contracts/feature-tests/composability/forwarder-legacy/src/fwd_nft_legacy.rs b/contracts/feature-tests/composability/forwarder-legacy/src/fwd_nft_legacy.rs index 5d922c2312..f2edb703c9 100644 --- a/contracts/feature-tests/composability/forwarder-legacy/src/fwd_nft_legacy.rs +++ b/contracts/feature-tests/composability/forwarder-legacy/src/fwd_nft_legacy.rs @@ -243,7 +243,7 @@ pub trait ForwarderNftModule: fwd_storage_legacy::ForwarderStorageModule { &amount, self.blockchain().get_gas_left(), &function, - &arguments.to_arg_buffer(), + &arguments.into_arg_buffer(), ); } diff --git a/contracts/feature-tests/composability/forwarder-queue/src/forwarder_queue.rs b/contracts/feature-tests/composability/forwarder-queue/src/forwarder_queue.rs index d3acd13ad4..dc1c9fe735 100644 --- a/contracts/feature-tests/composability/forwarder-queue/src/forwarder_queue.rs +++ b/contracts/feature-tests/composability/forwarder-queue/src/forwarder_queue.rs @@ -132,7 +132,7 @@ pub trait ForwarderQueue { to, gas_limit, endpoint_name, - args: args.to_arg_buffer(), + args: args.into_arg_buffer(), payments: payments.clone(), }); } diff --git a/contracts/feature-tests/composability/forwarder-raw/src/forwarder_raw_alt_init.rs b/contracts/feature-tests/composability/forwarder-raw/src/forwarder_raw_alt_init.rs index de16dfcff3..1ed99aa70d 100644 --- a/contracts/feature-tests/composability/forwarder-raw/src/forwarder_raw_alt_init.rs +++ b/contracts/feature-tests/composability/forwarder-raw/src/forwarder_raw_alt_init.rs @@ -20,7 +20,7 @@ pub trait ForwarderRawAlternativeInit: super::forwarder_raw_common::ForwarderRaw self.tx() .to(&to) .raw_call(endpoint_name) - .arguments_raw(args.to_arg_buffer()) + .arguments_raw(args.into_arg_buffer()) .async_call_and_exit(); } @@ -61,7 +61,7 @@ pub trait ForwarderRawAlternativeInit: super::forwarder_raw_common::ForwarderRaw .gas(half_gas) .egld(payment) .raw_call(endpoint_name) - .arguments_raw(args.to_arg_buffer()) + .arguments_raw(args.into_arg_buffer()) .returns(ReturnsRawResult) .sync_call(); diff --git a/contracts/feature-tests/composability/forwarder-raw/src/forwarder_raw_deploy_upgrade.rs b/contracts/feature-tests/composability/forwarder-raw/src/forwarder_raw_deploy_upgrade.rs index 803119c140..94de70ccc6 100644 --- a/contracts/feature-tests/composability/forwarder-raw/src/forwarder_raw_deploy_upgrade.rs +++ b/contracts/feature-tests/composability/forwarder-raw/src/forwarder_raw_deploy_upgrade.rs @@ -13,7 +13,7 @@ pub trait ForwarderRawDeployUpgrade { .raw_deploy() .code(code) .code_metadata(code_metadata) - .arguments_raw(args.to_arg_buffer()) + .arguments_raw(args.into_arg_buffer()) .gas(self.blockchain().get_gas_left()) .returns(ReturnsNewManagedAddress) .returns(ReturnsRawResult) @@ -32,7 +32,7 @@ pub trait ForwarderRawDeployUpgrade { .raw_deploy() .from_source(source_contract_address) .code_metadata(code_metadata) - .arguments_raw(args.to_arg_buffer()) + .arguments_raw(args.into_arg_buffer()) .gas(self.blockchain().get_gas_left()) .returns(ReturnsNewManagedAddress) .sync_call() @@ -51,7 +51,7 @@ pub trait ForwarderRawDeployUpgrade { .raw_upgrade() .code(new_code) .code_metadata(code_metadata) - .arguments_raw(args.to_arg_buffer()) + .arguments_raw(args.into_arg_buffer()) .upgrade_async_call_and_exit(); } @@ -68,7 +68,7 @@ pub trait ForwarderRawDeployUpgrade { .raw_upgrade() .from_source(source_contract_address) .code_metadata(code_metadata) - .arguments_raw(args.to_arg_buffer()) + .arguments_raw(args.into_arg_buffer()) .gas(self.blockchain().get_gas_left()) .upgrade_async_call_and_exit(); } diff --git a/contracts/feature-tests/composability/forwarder-raw/src/forwarder_raw_sync.rs b/contracts/feature-tests/composability/forwarder-raw/src/forwarder_raw_sync.rs index bd1188c1bb..d2d3f62bf1 100644 --- a/contracts/feature-tests/composability/forwarder-raw/src/forwarder_raw_sync.rs +++ b/contracts/feature-tests/composability/forwarder-raw/src/forwarder_raw_sync.rs @@ -36,7 +36,7 @@ pub trait ForwarderRawSync: super::forwarder_raw_common::ForwarderRawCommon { let payment = self.call_value().egld(); let one_third_gas = self.blockchain().get_gas_left() / 3; let half_payment = &*payment / 2u32; - let arg_buffer = args.to_arg_buffer(); + let arg_buffer = args.into_arg_buffer(); let result = self .tx() diff --git a/contracts/feature-tests/composability/forwarder/src/fwd_call_promise_direct.rs b/contracts/feature-tests/composability/forwarder/src/fwd_call_promise_direct.rs index 255bf46d6b..27e8e6c079 100644 --- a/contracts/feature-tests/composability/forwarder/src/fwd_call_promise_direct.rs +++ b/contracts/feature-tests/composability/forwarder/src/fwd_call_promise_direct.rs @@ -35,7 +35,7 @@ pub trait CallPromisesDirectModule { .to(&to) .raw_call(endpoint_name) .payment(payment) - .arguments_raw(args.to_arg_buffer()) + .arguments_raw(args.into_arg_buffer()) .gas(gas_limit) .callback(self.callbacks().the_one_callback(1001, 1002u32.into())) .gas_for_callback(extra_gas_for_callback) diff --git a/contracts/feature-tests/composability/forwarder/src/fwd_fallible.rs b/contracts/feature-tests/composability/forwarder/src/fwd_fallible.rs index 114f5d7665..e907c184fb 100644 --- a/contracts/feature-tests/composability/forwarder/src/fwd_fallible.rs +++ b/contracts/feature-tests/composability/forwarder/src/fwd_fallible.rs @@ -17,7 +17,7 @@ pub trait ForwarderFallibleModule { .to(&to) .gas(half_gas) .raw_call(endpoint_name) - .arguments_raw(args.to_arg_buffer()) + .arguments_raw(args.into_arg_buffer()) .returns(ReturnsHandledOrError::new().returns(ReturnsRawResult)) .sync_call_fallible(); diff --git a/contracts/feature-tests/composability/forwarder/src/fwd_nft.rs b/contracts/feature-tests/composability/forwarder/src/fwd_nft.rs index 45ef1c2111..dc298e1570 100644 --- a/contracts/feature-tests/composability/forwarder/src/fwd_nft.rs +++ b/contracts/feature-tests/composability/forwarder/src/fwd_nft.rs @@ -249,7 +249,7 @@ pub trait ForwarderNftModule: fwd_storage::ForwarderStorageModule { .to(&to) .gas(gas_left) .raw_call(function) - .arguments_raw(arguments.to_arg_buffer()) + .arguments_raw(arguments.into_arg_buffer()) .single_esdt(&token_identifier, nonce, &amount) .transfer_execute(); } diff --git a/framework/base/src/api/managed_types/managed_type_api_impl.rs b/framework/base/src/api/managed_types/managed_type_api_impl.rs index 64fc31d81e..a61136639d 100644 --- a/framework/base/src/api/managed_types/managed_type_api_impl.rs +++ b/framework/base/src/api/managed_types/managed_type_api_impl.rs @@ -60,6 +60,9 @@ pub trait ManagedTypeApiImpl: token_identifier_util::get_token_ticker_len(token_id_len) } + fn requires_managed_type_drop(&self) -> bool { + false + } fn drop_managed_buffer(&self, _handle: Self::ManagedBufferHandle) {} fn drop_big_float(&self, _handle: Self::BigFloatHandle) {} fn drop_big_int(&self, _handle: Self::BigIntHandle) {} diff --git a/framework/base/src/contract_base/wrappers/blockchain_wrapper.rs b/framework/base/src/contract_base/wrappers/blockchain_wrapper.rs index 3dda779af3..5d5affe722 100644 --- a/framework/base/src/contract_base/wrappers/blockchain_wrapper.rs +++ b/framework/base/src/contract_base/wrappers/blockchain_wrapper.rs @@ -499,8 +499,7 @@ where big_int_temp_handle.clone(), ); - let bu = BigUint::::from_handle(big_int_temp_handle); - // TODO: forget bu + let bu = ManagedRef::>::wrap_handle(big_int_temp_handle); // BigUint::::from_handle(big_int_temp_handle); bu.to_u64().unwrap_or(255) } } @@ -718,7 +717,7 @@ where result_handle.clone(), ); - let result = unsafe { ManagedBuffer::::from_handle(result_handle) }; + let result = unsafe { ManagedRef::>::wrap_handle(result_handle) }; // Decoding the response needs more research // Empty response means no address has transferRole for the token diff --git a/framework/base/src/contract_base/wrappers/storage_raw_wrapper.rs b/framework/base/src/contract_base/wrappers/storage_raw_wrapper.rs index de295425b1..d61032b062 100644 --- a/framework/base/src/contract_base/wrappers/storage_raw_wrapper.rs +++ b/framework/base/src/contract_base/wrappers/storage_raw_wrapper.rs @@ -6,10 +6,7 @@ use crate::api::HandleConstraints; use crate::codec::{TopDecode, TopEncode}; use crate::{ - api::{ - ErrorApi, ManagedTypeApi, StorageReadApi, StorageReadApiImpl, StorageWriteApi, - const_handles::MBUF_TEMPORARY_1, use_raw_handle, - }, + api::{ErrorApi, ManagedTypeApi, StorageReadApi, StorageReadApiImpl, StorageWriteApi}, storage::StorageKey, storage_get, storage_get::StorageGetErrorHandler, @@ -59,8 +56,7 @@ where V: TopDecode, { let key: StorageKey = storage_key.into(); - let result_buffer = - unsafe { ManagedBuffer::::from_handle(use_raw_handle(MBUF_TEMPORARY_1)) }; + let result_buffer = unsafe { ManagedBuffer::::new_uninit() }; A::storage_read_api_impl().storage_load_from_address( address.get_handle(), key.get_handle(), diff --git a/framework/base/src/storage/storage_set.rs b/framework/base/src/storage/storage_set.rs index f527992444..9ee302f237 100644 --- a/framework/base/src/storage/storage_set.rs +++ b/framework/base/src/storage/storage_set.rs @@ -52,7 +52,7 @@ where let handle: A::ManagedBufferHandle = use_raw_handle(const_handles::MBUF_TEMPORARY_1); A::managed_type_impl().mb_from_small_int_unsigned(handle.clone(), value as i64); - let managed_buffer = unsafe { ManagedBuffer::from_handle(handle) }; + let managed_buffer = unsafe { ManagedRef::wrap_handle(handle) }; self.set_managed_buffer(&managed_buffer); } @@ -61,7 +61,7 @@ where let handle: A::ManagedBufferHandle = use_raw_handle(const_handles::MBUF_TEMPORARY_1); A::managed_type_impl().mb_from_small_int_signed(handle.clone(), value); - let managed_buffer = unsafe { ManagedBuffer::from_handle(handle) }; + let managed_buffer = unsafe { ManagedRef::wrap_handle(handle) }; self.set_managed_buffer(&managed_buffer); } diff --git a/framework/base/src/types/interaction/tx_data/function_call.rs b/framework/base/src/types/interaction/tx_data/function_call.rs index 0be7c24c1d..fbf1cb05aa 100644 --- a/framework/base/src/types/interaction/tx_data/function_call.rs +++ b/framework/base/src/types/interaction/tx_data/function_call.rs @@ -125,7 +125,7 @@ where MultiValueEncoded::>::multi_decode_or_handle_err(input, h)?; Ok(FunctionCall { function_name, - arg_buffer: args.to_arg_buffer(), + arg_buffer: args.into_arg_buffer(), }) } } diff --git a/framework/base/src/types/managed/basic/managed_buffer.rs b/framework/base/src/types/managed/basic/managed_buffer.rs index bfa0b30a83..7693ae3b79 100644 --- a/framework/base/src/types/managed/basic/managed_buffer.rs +++ b/framework/base/src/types/managed/basic/managed_buffer.rs @@ -2,7 +2,7 @@ use crate::{ abi::{TypeAbi, TypeAbiFrom, TypeName}, api::{ ErrorApiImpl, HandleConstraints, InvalidSliceError, ManagedBufferApiImpl, ManagedTypeApi, - RawHandle, StaticVarApiImpl, use_raw_handle, + ManagedTypeApiImpl, RawHandle, StaticVarApiImpl, use_raw_handle, }, codec::{ DecodeErrorHandler, Empty, EncodeErrorHandler, NestedDecode, NestedDecodeInput, @@ -411,17 +411,15 @@ impl ManagedBuffer { impl Clone for ManagedBuffer { fn clone(&self) -> Self { - let api = M::managed_type_impl(); - let clone_handle = api.mb_new_empty(); - api.mb_append(clone_handle.clone(), self.handle.clone()); - unsafe { ManagedBuffer::from_handle(clone_handle) } + let cloned = ManagedBuffer::new(); + M::managed_type_impl().mb_append(cloned.get_handle(), self.handle.clone()); + cloned } } impl Drop for ManagedBuffer { fn drop(&mut self) { - // TODO: enable, after fixing all ownership issues - // M::managed_type_impl().drop_managed_buffer(self.handle.clone()); + M::managed_type_impl().drop_managed_buffer(self.handle.clone()); } } diff --git a/framework/base/src/types/managed/multi_value/egld_or_esdt_token_payment_multi_value.rs b/framework/base/src/types/managed/multi_value/egld_or_esdt_token_payment_multi_value.rs index 6022f38de4..08e1822a4b 100644 --- a/framework/base/src/types/managed/multi_value/egld_or_esdt_token_payment_multi_value.rs +++ b/framework/base/src/types/managed/multi_value/egld_or_esdt_token_payment_multi_value.rs @@ -39,8 +39,8 @@ impl ManagedVecItem for EgldOrEsdtTokenPaymentMultiValue { const SKIPS_RESERIALIZATION: bool = EgldOrEsdtTokenPayment::::SKIPS_RESERIALIZATION; type Ref<'a> = Ref<'a, Self>; - fn read_from_payload(payload: &Self::PAYLOAD) -> Self { - EgldOrEsdtTokenPayment::read_from_payload(payload).into() + unsafe fn read_from_payload(payload: &Self::PAYLOAD) -> Self { + unsafe { EgldOrEsdtTokenPayment::read_from_payload(payload).into() } } unsafe fn borrow_from_payload<'a>(payload: &Self::PAYLOAD) -> Self::Ref<'a> { diff --git a/framework/base/src/types/managed/multi_value/esdt_token_payment_multi_value.rs b/framework/base/src/types/managed/multi_value/esdt_token_payment_multi_value.rs index 01bc1d40e7..e71fab9ca3 100644 --- a/framework/base/src/types/managed/multi_value/esdt_token_payment_multi_value.rs +++ b/framework/base/src/types/managed/multi_value/esdt_token_payment_multi_value.rs @@ -45,8 +45,8 @@ impl ManagedVecItem for EsdtTokenPaymentMultiValue { const SKIPS_RESERIALIZATION: bool = EsdtTokenPayment::::SKIPS_RESERIALIZATION; type Ref<'a> = Ref<'a, Self>; - fn read_from_payload(payload: &Self::PAYLOAD) -> Self { - EsdtTokenPayment::read_from_payload(payload).into() + unsafe fn read_from_payload(payload: &Self::PAYLOAD) -> Self { + unsafe { EsdtTokenPayment::read_from_payload(payload).into() } } unsafe fn borrow_from_payload<'a>(payload: &Self::PAYLOAD) -> Self::Ref<'a> { diff --git a/framework/base/src/types/managed/multi_value/multi_value_encoded.rs b/framework/base/src/types/managed/multi_value/multi_value_encoded.rs index f0e8678f02..2702c926f7 100644 --- a/framework/base/src/types/managed/multi_value/multi_value_encoded.rs +++ b/framework/base/src/types/managed/multi_value/multi_value_encoded.rs @@ -17,7 +17,7 @@ use crate::{ }, contract_base::{ExitCodecErrorHandler, ManagedSerializer}, err_msg, - types::{ManagedArgBuffer, ManagedBuffer, ManagedType, ManagedVec, ManagedVecItem}, + types::{ManagedArgBuffer, ManagedBuffer, ManagedVec, ManagedVecItem}, }; use core::{iter::FromIterator, marker::PhantomData}; @@ -107,7 +107,11 @@ where M: ManagedTypeApi, { pub fn to_arg_buffer(&self) -> ManagedArgBuffer { - unsafe { ManagedArgBuffer::from_handle(self.raw_buffers.get_handle()) } + ManagedArgBuffer::from(self.raw_buffers.clone()) + } + + pub fn into_arg_buffer(self) -> ManagedArgBuffer { + ManagedArgBuffer::from(self.raw_buffers) } } diff --git a/framework/base/src/types/managed/multi_value/multi_value_managed_vec_counted.rs b/framework/base/src/types/managed/multi_value/multi_value_managed_vec_counted.rs index 4f51989a9b..c2d1b02d84 100644 --- a/framework/base/src/types/managed/multi_value/multi_value_managed_vec_counted.rs +++ b/framework/base/src/types/managed/multi_value/multi_value_managed_vec_counted.rs @@ -100,12 +100,12 @@ where const SKIPS_RESERIALIZATION: bool = false; type Ref<'a> = Self; - fn read_from_payload(payload: &Self::PAYLOAD) -> Self { - Self::from(ManagedVec::::read_from_payload(payload)) + unsafe fn read_from_payload(payload: &Self::PAYLOAD) -> Self { + unsafe { Self::from(ManagedVec::::read_from_payload(payload)) } } unsafe fn borrow_from_payload<'a>(payload: &Self::PAYLOAD) -> Self::Ref<'a> { - Self::read_from_payload(payload) + unsafe { Self::read_from_payload(payload) } } fn save_to_payload(self, payload: &mut Self::PAYLOAD) { diff --git a/framework/base/src/types/managed/multi_value/payment_multi_value.rs b/framework/base/src/types/managed/multi_value/payment_multi_value.rs index e049f6c480..dfb22388b6 100644 --- a/framework/base/src/types/managed/multi_value/payment_multi_value.rs +++ b/framework/base/src/types/managed/multi_value/payment_multi_value.rs @@ -39,8 +39,8 @@ impl ManagedVecItem for PaymentMultiValue { const SKIPS_RESERIALIZATION: bool = Payment::::SKIPS_RESERIALIZATION; type Ref<'a> = Ref<'a, Self>; - fn read_from_payload(payload: &Self::PAYLOAD) -> Self { - Payment::read_from_payload(payload).into() + unsafe fn read_from_payload(payload: &Self::PAYLOAD) -> Self { + unsafe { Payment::read_from_payload(payload).into() } } unsafe fn borrow_from_payload<'a>(payload: &Self::PAYLOAD) -> Self::Ref<'a> { diff --git a/framework/base/src/types/managed/wrapped/encoded_managed_vec_item.rs b/framework/base/src/types/managed/wrapped/encoded_managed_vec_item.rs index 205a219a2c..9fad5f9eca 100644 --- a/framework/base/src/types/managed/wrapped/encoded_managed_vec_item.rs +++ b/framework/base/src/types/managed/wrapped/encoded_managed_vec_item.rs @@ -14,7 +14,9 @@ where T: ManagedVecItem, { pub(crate) fn decode(&self) -> T { - T::read_from_payload(&self.encoded) + // TODO: not safe!! + // must revisit + unsafe { T::read_from_payload(&self.encoded) } } } diff --git a/framework/base/src/types/managed/wrapped/managed_decimal.rs b/framework/base/src/types/managed/wrapped/managed_decimal.rs index 4b1726d05b..34d41b269f 100644 --- a/framework/base/src/types/managed/wrapped/managed_decimal.rs +++ b/framework/base/src/types/managed/wrapped/managed_decimal.rs @@ -146,7 +146,7 @@ impl ManagedVecItem for ManagedDecimal { type Ref<'a> = Ref<'a, Self>; - fn read_from_payload(payload: &Self::PAYLOAD) -> Self { + unsafe fn read_from_payload(payload: &Self::PAYLOAD) -> Self { let mut index = 0; unsafe { Self { @@ -178,8 +178,8 @@ impl ManagedVecItem type Ref<'a> = Ref<'a, Self>; - fn read_from_payload(payload: &Self::PAYLOAD) -> Self { - Self::const_decimals_from_raw(BigUint::read_from_payload(payload)) + unsafe fn read_from_payload(payload: &Self::PAYLOAD) -> Self { + unsafe { Self::const_decimals_from_raw(BigUint::read_from_payload(payload)) } } unsafe fn borrow_from_payload<'a>(payload: &Self::PAYLOAD) -> Self::Ref<'a> { diff --git a/framework/base/src/types/managed/wrapped/managed_decimal/managed_decimal_signed.rs b/framework/base/src/types/managed/wrapped/managed_decimal/managed_decimal_signed.rs index 3c76e4b28f..06799395ad 100644 --- a/framework/base/src/types/managed/wrapped/managed_decimal/managed_decimal_signed.rs +++ b/framework/base/src/types/managed/wrapped/managed_decimal/managed_decimal_signed.rs @@ -196,7 +196,7 @@ impl ManagedVecItem for ManagedDecimalSigned type Ref<'a> = Ref<'a, Self>; - fn read_from_payload(payload: &Self::PAYLOAD) -> Self { + unsafe fn read_from_payload(payload: &Self::PAYLOAD) -> Self { let mut index = 0; unsafe { Self { @@ -228,8 +228,8 @@ impl ManagedVecItem type Ref<'a> = Ref<'a, Self>; - fn read_from_payload(payload: &Self::PAYLOAD) -> Self { - Self::const_decimals_from_raw(BigInt::read_from_payload(payload)) + unsafe fn read_from_payload(payload: &Self::PAYLOAD) -> Self { + unsafe { Self::const_decimals_from_raw(BigInt::read_from_payload(payload)) } } unsafe fn borrow_from_payload<'a>(payload: &Self::PAYLOAD) -> Self::Ref<'a> { diff --git a/framework/base/src/types/managed/wrapped/managed_option.rs b/framework/base/src/types/managed/wrapped/managed_option.rs index 844153c94d..62006035b1 100644 --- a/framework/base/src/types/managed/wrapped/managed_option.rs +++ b/framework/base/src/types/managed/wrapped/managed_option.rs @@ -206,14 +206,16 @@ where const SKIPS_RESERIALIZATION: bool = false; type Ref<'a> = Self; - fn read_from_payload(payload: &Self::PAYLOAD) -> Self { - let handle = use_raw_handle(i32::read_from_payload(payload)); - Self::new_with_handle(handle) + unsafe fn read_from_payload(payload: &Self::PAYLOAD) -> Self { + unsafe { + let handle = use_raw_handle(i32::read_from_payload(payload)); + Self::new_with_handle(handle) + } } unsafe fn borrow_from_payload<'a>(payload: &Self::PAYLOAD) -> Self::Ref<'a> { // TODO: managed ref - Self::read_from_payload(payload) + unsafe { Self::read_from_payload(payload) } } fn save_to_payload(self, payload: &mut Self::PAYLOAD) { diff --git a/framework/base/src/types/managed/wrapped/managed_ref_mut.rs b/framework/base/src/types/managed/wrapped/managed_ref_mut.rs index e017021d24..0abc304c6a 100644 --- a/framework/base/src/types/managed/wrapped/managed_ref_mut.rs +++ b/framework/base/src/types/managed/wrapped/managed_ref_mut.rs @@ -35,7 +35,7 @@ where /// Will completely disregard lifetimes, use with care. #[doc(hidden)] - pub(crate) unsafe fn wrap_handle(handle: T::OwnHandle) -> Self { + pub unsafe fn wrap_handle(handle: T::OwnHandle) -> Self { Self { _phantom_m: PhantomData, _phantom_t: PhantomData, diff --git a/framework/base/src/types/managed/wrapped/managed_vec.rs b/framework/base/src/types/managed/wrapped/managed_vec.rs index 07fdfdd987..809a1c3ada 100644 --- a/framework/base/src/types/managed/wrapped/managed_vec.rs +++ b/framework/base/src/types/managed/wrapped/managed_vec.rs @@ -9,7 +9,8 @@ use crate::{ }, types::{ ManagedBuffer, ManagedBufferNestedDecodeInput, ManagedType, ManagedVecItem, - ManagedVecRefIterator, ManagedVecRefMut, MultiValueEncoded, MultiValueManagedVec, + ManagedVecPayloadIterator, ManagedVecRefIterator, ManagedVecRefMut, MultiValueEncoded, + MultiValueManagedVec, }, }; use alloc::{format, vec::Vec}; @@ -55,7 +56,11 @@ where } unsafe fn forget_into_handle(self) -> Self::OwnHandle { - unsafe { self.buffer.forget_into_handle() } + unsafe { + let handle = core::ptr::read(&self.buffer.handle); + core::mem::forget(self); + handle + } } fn transmute_from_handle_ref(handle_ref: &M::ManagedBufferHandle) -> &Self { @@ -238,7 +243,7 @@ where pub(super) unsafe fn get_unsafe(&self, index: usize) -> T { let mut payload = T::PAYLOAD::new_buffer(); if self.load_item_payload(index, &mut payload) { - T::read_from_payload(&payload) + unsafe { T::read_from_payload(&payload) } } else { M::error_api_impl().signal_error(INDEX_OUT_OF_RANGE_MSG); } @@ -596,11 +601,18 @@ where other .buffer .load_slice(byte_index, other_payload.payload_slice_mut()); - let self_item = T::read_from_payload(&self_payload); - let other_item = T::read_from_payload(&other_payload); - if self_item != other_item { - return false; + unsafe { + // ok because of the forget below + let self_item = T::read_from_payload(&self_payload); + let other_item = T::read_from_payload(&other_payload); + + if self_item != other_item { + return false; + } + core::mem::forget(self_item); + core::mem::forget(other_item); } + byte_index += T::payload_size(); } true @@ -639,6 +651,24 @@ where } } +impl Drop for ManagedVec +where + M: ManagedTypeApi, + T: ManagedVecItem, +{ + fn drop(&mut self) { + unsafe { + if T::requires_drop() { + let iter = ManagedVecPayloadIterator::::new(self.get_handle()); + for payload in iter { + let item = T::read_from_payload(&payload); + core::mem::drop(item); + } + } + } + } +} + impl TopEncode for ManagedVec where M: ManagedTypeApi, diff --git a/framework/base/src/types/managed/wrapped/managed_vec_item.rs b/framework/base/src/types/managed/wrapped/managed_vec_item.rs index 210a602e09..bbb235bdec 100644 --- a/framework/base/src/types/managed/wrapped/managed_vec_item.rs +++ b/framework/base/src/types/managed/wrapped/managed_vec_item.rs @@ -8,7 +8,7 @@ use multiversx_chain_core::types::{EsdtLocalRole, EsdtTokenType}; use multiversx_sc_codec::multi_types::{MultiValue2, MultiValue3}; use crate::{ - api::{HandleConstraints, ManagedTypeApi, use_raw_handle}, + api::{HandleConstraints, ManagedTypeApi, ManagedTypeApiImpl, use_raw_handle}, types::{ BigInt, BigUint, EllipticCurve, EsdtTokenIdentifier, ManagedAddress, ManagedBuffer, ManagedByteArray, ManagedRef, ManagedType, ManagedVec, NonZeroBigUint, TokenId, @@ -25,7 +25,7 @@ use super::{ /// in the underlying managed buffer. /// Not all data needs to be stored as payload, for instance for most managed types /// the payload is just the handle, whereas the mai ndata is kept by the VM. -pub trait ManagedVecItem: 'static { +pub trait ManagedVecItem: Sized + 'static { /// Type managing the underlying binary representation in a ManagedVec.. type PAYLOAD: ManagedVecItemPayload; @@ -50,7 +50,12 @@ pub trait ManagedVecItem: 'static { } /// Parses given bytes as a an owned object. - fn read_from_payload(payload: &Self::PAYLOAD) -> Self; + /// + /// # Safety + /// + /// It creates a new object from a payload, which will drop. + /// This can lead to a double drop, in case the payload is also handled by another object. + unsafe fn read_from_payload(payload: &Self::PAYLOAD) -> Self; /// Parses given bytes as a representation of the object, either owned, or a reference. /// @@ -65,6 +70,25 @@ pub trait ManagedVecItem: 'static { /// /// Note that a destructor should not be called at this moment, since the ManagedVec will take ownership of the item. fn save_to_payload(self, payload: &mut Self::PAYLOAD); + + /// Signals that vec should drop all items one by one when being itself dropped. + /// + /// If false, iterating over all items on drop makes no sense. + fn requires_drop() -> bool { + false + } + + fn temp_decode(payload: &Self::PAYLOAD, f: F) -> R + where + F: FnOnce(&Self) -> R, + { + unsafe { + let item = Self::read_from_payload(payload); + let result = f(&item); + core::mem::forget(item); + result + } + } } /// Used by the ManagedVecItem derive. @@ -110,7 +134,7 @@ macro_rules! impl_int { const SKIPS_RESERIALIZATION: bool = true; type Ref<'a> = Self; - fn read_from_payload(payload: &Self::PAYLOAD) -> Self { + unsafe fn read_from_payload(payload: &Self::PAYLOAD) -> Self { $ty::from_be_bytes(payload.buffer.into_array()) } @@ -136,12 +160,12 @@ impl ManagedVecItem for usize { const SKIPS_RESERIALIZATION: bool = true; type Ref<'a> = Self; - fn read_from_payload(payload: &Self::PAYLOAD) -> Self { - u32::read_from_payload(payload) as usize + unsafe fn read_from_payload(payload: &Self::PAYLOAD) -> Self { + unsafe { u32::read_from_payload(payload) as usize } } unsafe fn borrow_from_payload<'a>(payload: &Self::PAYLOAD) -> Self::Ref<'a> { - Self::read_from_payload(payload) + unsafe { Self::read_from_payload(payload) } } fn save_to_payload(self, payload: &mut Self::PAYLOAD) { @@ -154,12 +178,12 @@ impl ManagedVecItem for bool { const SKIPS_RESERIALIZATION: bool = true; type Ref<'a> = Self; - fn read_from_payload(payload: &Self::PAYLOAD) -> Self { - u8::read_from_payload(payload) > 0 + unsafe fn read_from_payload(payload: &Self::PAYLOAD) -> Self { + unsafe { u8::read_from_payload(payload) > 0 } } unsafe fn borrow_from_payload<'a>(payload: &Self::PAYLOAD) -> Self::Ref<'a> { - Self::read_from_payload(payload) + unsafe { Self::read_from_payload(payload) } } fn save_to_payload(self, payload: &mut Self::PAYLOAD) { @@ -179,16 +203,16 @@ where const SKIPS_RESERIALIZATION: bool = false; type Ref<'a> = Ref<'a, Self>; - fn read_from_payload(payload: &Self::PAYLOAD) -> Self { + unsafe fn read_from_payload(payload: &Self::PAYLOAD) -> Self { let (p1, p2) = as ManagedVecItemPayloadAdd< T::PAYLOAD, >>::split_from_add(payload); - let disc = u8::read_from_payload(p1); + let disc = unsafe { u8::read_from_payload(p1) }; if disc == 0 { None } else { - Some(T::read_from_payload(p2)) + Some(unsafe { T::read_from_payload(p2) }) } } @@ -206,6 +230,10 @@ where t.save_to_payload(p2); } } + + fn requires_drop() -> bool { + T::requires_drop() + } } macro_rules! impl_managed_type { @@ -215,8 +243,8 @@ macro_rules! impl_managed_type { const SKIPS_RESERIALIZATION: bool = false; type Ref<'a> = ManagedRef<'a, M, Self>; - fn read_from_payload(payload: &Self::PAYLOAD) -> Self { - let handle = use_raw_handle(i32::read_from_payload(payload)); + unsafe fn read_from_payload(payload: &Self::PAYLOAD) -> Self { + let handle = use_raw_handle(unsafe { i32::read_from_payload(payload) }); unsafe { Self::from_handle(handle) } } @@ -253,8 +281,8 @@ where const SKIPS_RESERIALIZATION: bool = false; type Ref<'a> = ManagedRef<'a, M, Self>; - fn read_from_payload(payload: &Self::PAYLOAD) -> Self { - let handle = use_raw_handle(i32::read_from_payload(payload)); + unsafe fn read_from_payload(payload: &Self::PAYLOAD) -> Self { + let handle = use_raw_handle(unsafe { i32::read_from_payload(payload) }); unsafe { Self::from_handle(handle) } } @@ -269,6 +297,10 @@ where let handle = unsafe { self.forget_into_handle() }; handle.get_raw_handle().save_to_payload(payload); } + + fn requires_drop() -> bool { + M::managed_type_impl().requires_managed_type_drop() + } } impl ManagedVecItem for ManagedVec @@ -280,8 +312,8 @@ where const SKIPS_RESERIALIZATION: bool = false; type Ref<'a> = ManagedRef<'a, M, Self>; - fn read_from_payload(payload: &Self::PAYLOAD) -> Self { - let handle = use_raw_handle(i32::read_from_payload(payload)); + unsafe fn read_from_payload(payload: &Self::PAYLOAD) -> Self { + let handle = use_raw_handle(unsafe { i32::read_from_payload(payload) }); unsafe { Self::from_handle(handle) } } @@ -296,6 +328,10 @@ where let handle = unsafe { self.forget_into_handle() }; handle.get_raw_handle().save_to_payload(payload); } + + fn requires_drop() -> bool { + M::managed_type_impl().requires_managed_type_drop() + } } impl ManagedVecItem for EsdtTokenType { @@ -303,12 +339,12 @@ impl ManagedVecItem for EsdtTokenType { const SKIPS_RESERIALIZATION: bool = true; type Ref<'a> = Self; - fn read_from_payload(payload: &Self::PAYLOAD) -> Self { - u8::read_from_payload(payload).into() + unsafe fn read_from_payload(payload: &Self::PAYLOAD) -> Self { + unsafe { u8::read_from_payload(payload).into() } } unsafe fn borrow_from_payload<'a>(payload: &Self::PAYLOAD) -> Self::Ref<'a> { - Self::read_from_payload(payload) + unsafe { Self::read_from_payload(payload) } } fn save_to_payload(self, payload: &mut Self::PAYLOAD) { @@ -321,12 +357,12 @@ impl ManagedVecItem for EsdtLocalRole { const SKIPS_RESERIALIZATION: bool = false; // TODO: might be ok to be true, but needs testing type Ref<'a> = Self; - fn read_from_payload(payload: &Self::PAYLOAD) -> Self { - u16::read_from_payload(payload).into() + unsafe fn read_from_payload(payload: &Self::PAYLOAD) -> Self { + unsafe { u16::read_from_payload(payload).into() } } unsafe fn borrow_from_payload<'a>(payload: &Self::PAYLOAD) -> Self::Ref<'a> { - Self::read_from_payload(payload) + unsafe { Self::read_from_payload(payload) } } fn save_to_payload(self, payload: &mut Self::PAYLOAD) { @@ -344,7 +380,7 @@ where const SKIPS_RESERIALIZATION: bool = T1::SKIPS_RESERIALIZATION && T2::SKIPS_RESERIALIZATION; type Ref<'a> = Ref<'a, Self>; - fn read_from_payload(payload: &Self::PAYLOAD) -> Self { + unsafe fn read_from_payload(payload: &Self::PAYLOAD) -> Self { let mut index = 0; unsafe { ( @@ -381,7 +417,7 @@ where const SKIPS_RESERIALIZATION: bool = T1::SKIPS_RESERIALIZATION && T2::SKIPS_RESERIALIZATION; type Ref<'a> = Ref<'a, Self>; - fn read_from_payload(payload: &Self::PAYLOAD) -> Self { + unsafe fn read_from_payload(payload: &Self::PAYLOAD) -> Self { let mut index = 0; unsafe { ( diff --git a/framework/base/src/types/managed/wrapped/managed_vec_iter_owned.rs b/framework/base/src/types/managed/wrapped/managed_vec_iter_owned.rs index f4712e7464..13c2aa6e08 100644 --- a/framework/base/src/types/managed/wrapped/managed_vec_iter_owned.rs +++ b/framework/base/src/types/managed/wrapped/managed_vec_iter_owned.rs @@ -54,7 +54,8 @@ where fn next(&mut self) -> Option { let payload = self.payload_iter.next()?; - Some(T::read_from_payload(&payload)) + // ok, because the iterator has ownership over the payload and no drop + unsafe { Some(T::read_from_payload(&payload)) } } fn size_hint(&self) -> (usize, Option) { @@ -76,7 +77,8 @@ where { fn next_back(&mut self) -> Option { let payload = self.payload_iter.next_back()?; - Some(T::read_from_payload(&payload)) + // ok, because the iterator has ownership over the payload and no drop + unsafe { Some(T::read_from_payload(&payload)) } } } diff --git a/framework/base/src/types/managed/wrapped/managed_vec_ref.rs b/framework/base/src/types/managed/wrapped/managed_vec_ref.rs index 76ff779be6..0ab6a46377 100644 --- a/framework/base/src/types/managed/wrapped/managed_vec_ref.rs +++ b/framework/base/src/types/managed/wrapped/managed_vec_ref.rs @@ -1,3 +1,4 @@ +use super::ManagedVecItemPayload; use crate::types::ManagedVecItem; use core::{borrow::Borrow, fmt::Debug, marker::PhantomData, mem::ManuallyDrop, ops::Deref}; @@ -39,9 +40,15 @@ where T: ManagedVecItem, { fn drop(&mut self) { - // TODO: improve + // the payload is a dummy + // it is used because save_to_payload does a great job doing the soft deallocation needed here + // + // TODO: the saving as payload is not necessary, figure out if it is worth optimizing + // by adding a special soft drop method to ManagedVecItem + let mut dummy_payload = T::PAYLOAD::new_buffer(); unsafe { - ManuallyDrop::drop(&mut self.item); + let inner = ManuallyDrop::take(&mut self.item); + inner.save_to_payload(&mut dummy_payload); } } } diff --git a/framework/base/src/types/managed/wrapped/managed_vec_ref_mut.rs b/framework/base/src/types/managed/wrapped/managed_vec_ref_mut.rs index 17df354216..4a53ed8db5 100644 --- a/framework/base/src/types/managed/wrapped/managed_vec_ref_mut.rs +++ b/framework/base/src/types/managed/wrapped/managed_vec_ref_mut.rs @@ -53,13 +53,16 @@ where T: ManagedVecItem, { fn drop(&mut self) { + // This drop saves the item back into the p-arent ManagedVec. + // + // The `set` method also handles soft deallocation + // (freeing of the handle, without deallocating the underlying resource). let item = unsafe { ManuallyDrop::take(&mut self.item) }; unsafe { - let _ = - ManagedRefMut::>::wrap_handle(self.managed_vec_handle.clone()) - .set(self.item_index, item); + let mut parent_ref = + ManagedRefMut::>::wrap_handle(self.managed_vec_handle.clone()); + let _ = parent_ref.set(self.item_index, item); } - // core::mem::forget(item); } } diff --git a/framework/base/src/types/managed/wrapped/token/egld_or_esdt_token_payment.rs b/framework/base/src/types/managed/wrapped/token/egld_or_esdt_token_payment.rs index d3bee04dc7..6e5e80a477 100644 --- a/framework/base/src/types/managed/wrapped/token/egld_or_esdt_token_payment.rs +++ b/framework/base/src/types/managed/wrapped/token/egld_or_esdt_token_payment.rs @@ -154,7 +154,7 @@ impl ManagedVecItem for EgldOrEsdtTokenPayment { const SKIPS_RESERIALIZATION: bool = false; type Ref<'a> = Ref<'a, Self>; - fn read_from_payload(payload: &Self::PAYLOAD) -> Self { + unsafe fn read_from_payload(payload: &Self::PAYLOAD) -> Self { let mut index = 0; unsafe { EgldOrEsdtTokenPayment { diff --git a/framework/base/src/types/managed/wrapped/token/esdt_token_payment.rs b/framework/base/src/types/managed/wrapped/token/esdt_token_payment.rs index 44e021c366..4d76a306b3 100644 --- a/framework/base/src/types/managed/wrapped/token/esdt_token_payment.rs +++ b/framework/base/src/types/managed/wrapped/token/esdt_token_payment.rs @@ -192,7 +192,7 @@ impl ManagedVecItem for EsdtTokenPayment { const SKIPS_RESERIALIZATION: bool = false; type Ref<'a> = Ref<'a, Self>; - fn read_from_payload(payload: &Self::PAYLOAD) -> Self { + unsafe fn read_from_payload(payload: &Self::PAYLOAD) -> Self { let mut index = 0; unsafe { EsdtTokenPayment { diff --git a/framework/base/src/types/managed/wrapped/token/payment.rs b/framework/base/src/types/managed/wrapped/token/payment.rs index 1a1257e829..a6aad8ad22 100644 --- a/framework/base/src/types/managed/wrapped/token/payment.rs +++ b/framework/base/src/types/managed/wrapped/token/payment.rs @@ -169,7 +169,7 @@ impl ManagedVecItem for Payment { const SKIPS_RESERIALIZATION: bool = false; type Ref<'a> = Ref<'a, Self>; - fn read_from_payload(payload: &Self::PAYLOAD) -> Self { + unsafe fn read_from_payload(payload: &Self::PAYLOAD) -> Self { let mut index = 0; unsafe { Payment { diff --git a/framework/derive/src/managed_vec_item_derive.rs b/framework/derive/src/managed_vec_item_derive.rs index a3742d09d1..4f7b328bab 100644 --- a/framework/derive/src/managed_vec_item_derive.rs +++ b/framework/derive/src/managed_vec_item_derive.rs @@ -158,7 +158,7 @@ fn enum_derive(data_enum: &syn::DataEnum, ast: &syn::DeriveInput) -> TokenStream const SKIPS_RESERIALIZATION: bool = #skips_reserialization; type Ref<'a> = multiversx_sc::types::Ref<'a, Self>; - fn read_from_payload(payload: &Self::PAYLOAD) -> Self { + unsafe fn read_from_payload(payload: &Self::PAYLOAD) -> Self { let mut index = 0; unsafe { @@ -225,7 +225,7 @@ fn struct_derive(data_struct: &syn::DataStruct, ast: &syn::DeriveInput) -> Token const SKIPS_RESERIALIZATION: bool = #(#skips_reserialization_snippets)&&*; type Ref<'a> = multiversx_sc::types::Ref<'a, Self>; - fn read_from_payload(payload: &Self::PAYLOAD) -> Self { + unsafe fn read_from_payload(payload: &Self::PAYLOAD) -> Self { let mut index = 0; unsafe { diff --git a/framework/scenario/src/api/impl_vh/debug_api.rs b/framework/scenario/src/api/impl_vh/debug_api.rs index 531a54f5a2..d1e5517497 100644 --- a/framework/scenario/src/api/impl_vh/debug_api.rs +++ b/framework/scenario/src/api/impl_vh/debug_api.rs @@ -25,7 +25,9 @@ impl VMHooksApiBackend for DebugApiBackend { let tx_context_ref = instance.tx_context_ref.clone(); let vh_context = TxVMHooksContext::new(tx_context_ref, ContractDebugInstanceState); let mut dispatcher = VMHooksDispatcher::new(vh_context); - f(&mut dispatcher).unwrap_or_else(|err| ContractDebugInstanceState::early_exit_panic(err)) + let result = f(&mut dispatcher); + std::mem::drop(dispatcher); + result.unwrap_or_else(|err| ContractDebugInstanceState::early_exit_panic(err)) } fn with_vm_hooks_ctx_1(handle: Self::HandleType, f: F) -> R @@ -35,7 +37,9 @@ impl VMHooksApiBackend for DebugApiBackend { let tx_context_ref = handle.to_tx_context_ref(); let vh_context = TxVMHooksContext::new(tx_context_ref, ContractDebugInstanceState); let mut dispatcher = VMHooksDispatcher::new(vh_context); - f(&mut dispatcher).unwrap_or_else(|err| ContractDebugInstanceState::early_exit_panic(err)) + let result = f(&mut dispatcher); + std::mem::drop(dispatcher); + result.unwrap_or_else(|err| ContractDebugInstanceState::early_exit_panic(err)) } fn with_vm_hooks_ctx_2(handle1: Self::HandleType, handle2: Self::HandleType, f: F) -> R diff --git a/framework/scenario/src/api/impl_vh/debug_handle_vh.rs b/framework/scenario/src/api/impl_vh/debug_handle_vh.rs index 086d166d17..7759542fae 100644 --- a/framework/scenario/src/api/impl_vh/debug_handle_vh.rs +++ b/framework/scenario/src/api/impl_vh/debug_handle_vh.rs @@ -76,6 +76,7 @@ impl core::fmt::Debug for DebugHandle { impl HandleConstraints for DebugHandle { fn new(handle: multiversx_sc::api::RawHandle) -> Self { + println!("new handle {handle}"); let context = ContractDebugStack::static_peek().tx_context_ref.downgrade(); DebugHandle::new_with_explicit_context_ref(context, handle) } 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 9357f5b094..29789717b0 100644 --- a/framework/scenario/src/api/impl_vh/single_tx_api.rs +++ b/framework/scenario/src/api/impl_vh/single_tx_api.rs @@ -29,8 +29,9 @@ impl VMHooksApiBackend for SingleTxApiBackend { SINGLE_TX_API_VH_CELL.with(|cell| { let vh_context = cell.lock().unwrap().clone(); let mut dispatcher = VMHooksDispatcher::new(vh_context); - f(&mut dispatcher) - .unwrap_or_else(|err| ContractDebugInstanceState::early_exit_panic(err)) + let result = f(&mut dispatcher); + std::mem::drop(dispatcher); + result.unwrap_or_else(|err| ContractDebugInstanceState::early_exit_panic(err)) }) } diff --git a/framework/scenario/tests/derive_managed_vec_item_biguint_test.rs b/framework/scenario/tests/derive_managed_vec_item_biguint_test.rs index a60a688c93..ce64e9fe75 100644 --- a/framework/scenario/tests/derive_managed_vec_item_biguint_test.rs +++ b/framework/scenario/tests/derive_managed_vec_item_biguint_test.rs @@ -61,9 +61,10 @@ fn managed_struct_from_bytes_reader() { let handle_bytes = s.big_uint.get_handle().to_be_bytes(); let arr: [u8; 8] = [0xff, 0xff, 0xff, handle_bytes[3], 0x00, 0x01, 0x23, 0x45]; - let struct_from_bytes = - as multiversx_sc::types::ManagedVecItem>::read_from_payload( - &arr.into() - ); - assert_eq!(s, struct_from_bytes); + as multiversx_sc::types::ManagedVecItem>::temp_decode( + &arr.into(), + |struct_from_bytes| { + assert_eq!(&s, struct_from_bytes); + }, + ); } diff --git a/framework/scenario/tests/derive_managed_vec_item_decimal_test.rs b/framework/scenario/tests/derive_managed_vec_item_decimal_test.rs index 554942bd36..4c2016b41a 100644 --- a/framework/scenario/tests/derive_managed_vec_item_decimal_test.rs +++ b/framework/scenario/tests/derive_managed_vec_item_decimal_test.rs @@ -58,10 +58,11 @@ fn struct_with_decimal_read_write() { s.clone(), &mut payload, ); - let struct_from_bytes = + let struct_from_bytes = unsafe { as multiversx_sc::types::ManagedVecItem>::read_from_payload( &payload - ); + ) + }; assert_eq!(struct_from_bytes, s); // check payload diff --git a/framework/scenario/tests/derive_managed_vec_item_enum_1.rs b/framework/scenario/tests/derive_managed_vec_item_enum_1.rs index f2f0805cb6..b2eb71bdaa 100644 --- a/framework/scenario/tests/derive_managed_vec_item_enum_1.rs +++ b/framework/scenario/tests/derive_managed_vec_item_enum_1.rs @@ -65,29 +65,34 @@ fn enum_to_bytes_writer_variant_3() { #[test] fn enum_from_bytes_reader_variant_1() { let payload = [0, 0, 0, 0, 0, 0, 0, 0, 0]; - let enum_from_bytes = - ::read_from_payload( - &payload.into(), - ); - assert_eq!(enum_from_bytes, EnumWithFields::Variant1(0)); + + ::temp_decode( + &payload.into(), + |enum_from_bytes| { + assert_eq!(enum_from_bytes, &EnumWithFields::Variant1(0)); + }, + ); } #[test] fn enum_from_bytes_reader_variant_2() { let payload = [1, 0, 0, 0, 0, 0, 0, 0, 0]; - let enum_from_bytes = - ::read_from_payload( - &payload.into(), - ); - assert_eq!(enum_from_bytes, EnumWithFields::Variant2); + + ::temp_decode( + &payload.into(), + |enum_from_bytes| { + assert_eq!(enum_from_bytes, &EnumWithFields::Variant2); + }, + ); } #[test] fn enum_from_bytes_reader_variant_3() { let payload = [2, 0, 0, 0, 0, 0, 0, 0, 4]; - let enum_from_bytes = - ::read_from_payload( - &payload.into(), - ); - assert_eq!(enum_from_bytes, EnumWithFields::Variant3(4)); + ::temp_decode( + &payload.into(), + |enum_from_bytes| { + assert_eq!(enum_from_bytes, &EnumWithFields::Variant3(4)); + }, + ); } diff --git a/framework/scenario/tests/derive_managed_vec_item_enum_simple.rs b/framework/scenario/tests/derive_managed_vec_item_enum_simple.rs index 2dfdd76c63..f5083ce29c 100644 --- a/framework/scenario/tests/derive_managed_vec_item_enum_simple.rs +++ b/framework/scenario/tests/derive_managed_vec_item_enum_simple.rs @@ -41,7 +41,10 @@ fn enum_to_bytes_writer() { #[test] fn enum_from_bytes_reader() { - let enum_from_bytes = - ::read_from_payload(&[1u8].into()); - assert_eq!(enum_from_bytes, SimpleEnum::Variant2); + ::temp_decode( + &[1u8].into(), + |enum_from_bytes| { + assert_eq!(enum_from_bytes, &SimpleEnum::Variant2); + }, + ); } diff --git a/framework/scenario/tests/derive_managed_vec_item_esdt_token_payment_test.rs b/framework/scenario/tests/derive_managed_vec_item_esdt_token_payment_test.rs index c4c3cb92d8..e0ca8f4279 100644 --- a/framework/scenario/tests/derive_managed_vec_item_esdt_token_payment_test.rs +++ b/framework/scenario/tests/derive_managed_vec_item_esdt_token_payment_test.rs @@ -93,10 +93,10 @@ fn struct_from_bytes_reader() { handle3[1], handle3[2], handle3[3], handle4[0], handle4[1], handle4[2], handle4[3], ]; - let struct_from_bytes = - as multiversx_sc::types::ManagedVecItem>::read_from_payload( - &arr.into() - ); - - assert_eq!(s, struct_from_bytes); + as multiversx_sc::types::ManagedVecItem>::temp_decode( + &arr.into(), + |struct_from_bytes| { + assert_eq!(&s, struct_from_bytes); + }, + ); } diff --git a/framework/scenario/tests/derive_managed_vec_item_struct_1_test.rs b/framework/scenario/tests/derive_managed_vec_item_struct_1_test.rs index 39642b0774..88204e1dde 100644 --- a/framework/scenario/tests/derive_managed_vec_item_struct_1_test.rs +++ b/framework/scenario/tests/derive_managed_vec_item_struct_1_test.rs @@ -89,7 +89,10 @@ fn struct_1_from_bytes_reader() { 0x00, ]; - let struct_from_bytes = - ::read_from_payload(&arr.into()); - assert_eq!(s, struct_from_bytes); + ::temp_decode( + &arr.into(), + |struct_from_bytes| { + assert_eq!(&s, struct_from_bytes); + }, + ); } diff --git a/framework/scenario/tests/derive_managed_vec_item_struct_2_test.rs b/framework/scenario/tests/derive_managed_vec_item_struct_2_test.rs index 5d0542a24d..f6728c7874 100644 --- a/framework/scenario/tests/derive_managed_vec_item_struct_2_test.rs +++ b/framework/scenario/tests/derive_managed_vec_item_struct_2_test.rs @@ -79,7 +79,10 @@ fn struct_2_from_bytes_reader() { /* arr */ 0x61, 0x11, 0x62, 0x22, ]; - let struct_from_bytes = - ::read_from_payload(&payload.into()); - assert_eq!(expected_struct, struct_from_bytes); + ::temp_decode( + &payload.into(), + |struct_from_bytes| { + assert_eq!(&expected_struct, struct_from_bytes); + }, + ); } diff --git a/framework/scenario/tests/managed_ref_test.rs b/framework/scenario/tests/managed_ref_test.rs index 0b296f43a4..df6112c5c1 100644 --- a/framework/scenario/tests/managed_ref_test.rs +++ b/framework/scenario/tests/managed_ref_test.rs @@ -1,9 +1,9 @@ use core::fmt::Debug; use multiversx_sc::{ - api::ManagedTypeApi, + api::{ManagedTypeApi, use_raw_handle}, types::{ BigInt, BigUint, EsdtTokenIdentifier, ManagedAddress, ManagedBuffer, ManagedByteArray, - ManagedRef, ManagedType, + ManagedRef, ManagedRefMut, ManagedType, }, }; use multiversx_sc_scenario::api::StaticApi; @@ -56,3 +56,25 @@ fn test_managed_ref_eq() { BigUint::::from(2u32).as_ref() ); } + +#[test] +fn test_managed_ref_no_drop() { + const INVALID_HANDLE: i32 = 1000; + unsafe { + let _r = ManagedRef::<'static, StaticApi, ManagedBuffer>::wrap_handle( + use_raw_handle(INVALID_HANDLE), + ); + } + + unsafe { + let mut r = ManagedRefMut::<'static, StaticApi, ManagedBuffer>::wrap_handle( + use_raw_handle(INVALID_HANDLE), + ); + r.overwrite(b"abc"); + } + + unsafe { + let r = ManagedBuffer::::from_handle(use_raw_handle(INVALID_HANDLE)); + assert_eq!(r.to_vec(), b"abc"); + } +}