From 31c3a9a3e2382352a66c3630331153e2300b1954 Mon Sep 17 00:00:00 2001 From: Andrei Marinica Date: Thu, 28 Nov 2024 19:13:37 +0200 Subject: [PATCH 1/5] ManagedVecItem - lo longer implemented for handles directly --- .../base/src/api/managed_types/handles.rs | 7 ++---- .../src/api/impl_vh/debug_handle_vh.rs | 23 +------------------ 2 files changed, 3 insertions(+), 27 deletions(-) diff --git a/framework/base/src/api/managed_types/handles.rs b/framework/base/src/api/managed_types/handles.rs index 5a8f17ba9d..4c4c89a719 100644 --- a/framework/base/src/api/managed_types/handles.rs +++ b/framework/base/src/api/managed_types/handles.rs @@ -10,15 +10,12 @@ pub trait HandleTypeInfo { use crate::codec::TryStaticCast; -use crate::{ - api::{ErrorApi, ErrorApiImpl}, - types::ManagedVecItem, -}; +use crate::api::{ErrorApi, ErrorApiImpl}; pub type RawHandle = i32; pub trait HandleConstraints: - ManagedVecItem + TryStaticCast + Debug + Clone + From + PartialEq + PartialEq + TryStaticCast + Debug + Clone + From + PartialEq + PartialEq { fn new(handle: RawHandle) -> Self; fn to_be_bytes(&self) -> [u8; 4]; 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 64fcd15fa9..5c2a60c022 100644 --- a/framework/scenario/src/api/impl_vh/debug_handle_vh.rs +++ b/framework/scenario/src/api/impl_vh/debug_handle_vh.rs @@ -1,8 +1,7 @@ use multiversx_chain_vm::tx_mock::{TxContext, TxContextStack}; use multiversx_sc::{ - api::{use_raw_handle, HandleConstraints, RawHandle}, + api::{HandleConstraints, RawHandle}, codec::TryStaticCast, - types::ManagedVecItem, }; use std::sync::Arc; @@ -76,24 +75,4 @@ impl From for DebugHandle { } } -impl ManagedVecItem for DebugHandle { - type PAYLOAD = ::PAYLOAD; - - const SKIPS_RESERIALIZATION: bool = ::SKIPS_RESERIALIZATION; - - type Ref<'a> = Self; - - fn read_from_payload(payload: &Self::PAYLOAD) -> Self { - use_raw_handle(RawHandle::read_from_payload(payload)) - } - - unsafe fn borrow_from_payload<'a>(payload: &Self::PAYLOAD) -> Self::Ref<'a> { - Self::read_from_payload(payload) - } - - fn save_to_payload(self, payload: &mut Self::PAYLOAD) { - self.get_raw_handle().save_to_payload(payload); - } -} - impl TryStaticCast for DebugHandle {} From 16fac80f5e22e8d0c85cb1ca588edb5e1aa57f0c Mon Sep 17 00:00:00 2001 From: Andrei Marinica Date: Fri, 29 Nov 2024 10:58:10 +0200 Subject: [PATCH 2/5] ManagedVecItem - struct derive yields ManagedVecRef --- .../examples/order-book/pair/src/common.rs | 2 +- .../examples/order-book/pair/src/events.rs | 8 +-- .../examples/order-book/pair/src/orders.rs | 2 +- .../src/rewards_distribution.rs | 6 +-- .../src/distribution_module.rs | 2 +- .../src/governance/governance_proposal.rs | 2 +- contracts/modules/src/governance/mod.rs | 4 +- .../esdt_token_payment_multi_value.rs | 7 ++- framework/base/src/types/managed/wrapped.rs | 2 + .../types/managed/wrapped/managed_vec_item.rs | 6 +-- .../types/managed/wrapped/managed_vec_ref.rs | 54 +++++++++++++++++++ .../derive/src/managed_vec_item_derive.rs | 5 +- 12 files changed, 77 insertions(+), 23 deletions(-) create mode 100644 framework/base/src/types/managed/wrapped/managed_vec_ref.rs diff --git a/contracts/examples/order-book/pair/src/common.rs b/contracts/examples/order-book/pair/src/common.rs index 7728e4c364..85b1c1bca8 100644 --- a/contracts/examples/order-book/pair/src/common.rs +++ b/contracts/examples/order-book/pair/src/common.rs @@ -8,7 +8,7 @@ pub const FREE_ORDER_FROM_STORAGE_MIN_PENALTIES: u64 = 6; #[type_abi] #[derive( - ManagedVecItem, TopEncode, TopDecode, NestedEncode, NestedDecode, PartialEq, Eq, Clone, + ManagedVecItem, TopEncode, TopDecode, NestedEncode, NestedDecode, PartialEq, Eq, Clone, Copy )] pub enum OrderType { Buy, diff --git a/contracts/examples/order-book/pair/src/events.rs b/contracts/examples/order-book/pair/src/events.rs index ddbd6a3496..f20331f44f 100644 --- a/contracts/examples/order-book/pair/src/events.rs +++ b/contracts/examples/order-book/pair/src/events.rs @@ -31,7 +31,7 @@ pub trait EventsModule { for order in orders.iter() { let order_type = order.order_type; let order_id = order.id; - let order_creator = order.creator; + let order_creator = &order.creator; self.match_order_event(&caller, epoch, order_type, order_id, order_creator); } @@ -44,7 +44,7 @@ pub trait EventsModule { for order in orders.iter() { let order_type = order.order_type; let order_id = order.id; - let order_creator = order.creator; + let order_creator = &order.creator; self.free_order_event(&caller, epoch, order_type, order_id, order_creator); } @@ -75,7 +75,7 @@ pub trait EventsModule { #[indexed] epoch: u64, #[indexed] order_type: OrderType, #[indexed] order_id: u64, - #[indexed] order_creator: ManagedAddress, + #[indexed] order_creator: &ManagedAddress, ); #[event("free_order")] @@ -85,6 +85,6 @@ pub trait EventsModule { #[indexed] epoch: u64, #[indexed] order_type: OrderType, #[indexed] order_id: u64, - #[indexed] order_creator: ManagedAddress, + #[indexed] order_creator: &ManagedAddress, ); } diff --git a/contracts/examples/order-book/pair/src/orders.rs b/contracts/examples/order-book/pair/src/orders.rs index 1ec11afee4..2452cb0b16 100644 --- a/contracts/examples/order-book/pair/src/orders.rs +++ b/contracts/examples/order-book/pair/src/orders.rs @@ -282,7 +282,7 @@ pub trait OrdersModule: let mut orders_vec = MultiValueManagedVec::new(); for order in orders.iter() { if order.order_type == order_type { - orders_vec.push(order); + orders_vec.push(order.clone()); } } diff --git a/contracts/examples/rewards-distribution/src/rewards_distribution.rs b/contracts/examples/rewards-distribution/src/rewards_distribution.rs index 7300fcaf88..ecbf2b7d7c 100644 --- a/contracts/examples/rewards-distribution/src/rewards_distribution.rs +++ b/contracts/examples/rewards-distribution/src/rewards_distribution.rs @@ -21,7 +21,7 @@ pub struct Bracket { } #[type_abi] -#[derive(ManagedVecItem, NestedEncode, NestedDecode)] +#[derive(ManagedVecItem, NestedEncode, NestedDecode, Clone)] pub struct ComputedBracket { pub end_index: u64, pub nft_reward_percent: BigUint, @@ -74,7 +74,7 @@ pub trait RewardsDistribution: .unwrap_or_else(|| self.new_raffle()); let mut rng = RandomnessSource::default(); - let mut bracket = raffle.computed_brackets.get(0); + let mut bracket = raffle.computed_brackets.get(0).clone(); let run_result = self.run_while_it_has_gas(DEFAULT_MIN_GAS_TO_SAVE_PROGRESS, || { let ticket = self.shuffle_and_pick_single_ticket( @@ -138,7 +138,7 @@ pub trait RewardsDistribution: ) { while ticket > bracket.end_index { computed_brackets.remove(0); - *bracket = computed_brackets.get(0); + *bracket = computed_brackets.get(0).clone(); } } diff --git a/contracts/examples/seed-nft-minter/src/distribution_module.rs b/contracts/examples/seed-nft-minter/src/distribution_module.rs index 54f8bf2586..cebd751806 100644 --- a/contracts/examples/seed-nft-minter/src/distribution_module.rs +++ b/contracts/examples/seed-nft-minter/src/distribution_module.rs @@ -35,7 +35,7 @@ pub trait DistributionModule { } self.tx() .to(&distribution.address) - .raw_call(distribution.endpoint) + .raw_call(distribution.endpoint.clone()) .egld_or_single_esdt(token_id, token_nonce, &payment_amount) .gas(distribution.gas_limit) .transfer_execute(); diff --git a/contracts/modules/src/governance/governance_proposal.rs b/contracts/modules/src/governance/governance_proposal.rs index 60d0fa27f0..db3f28038d 100644 --- a/contracts/modules/src/governance/governance_proposal.rs +++ b/contracts/modules/src/governance/governance_proposal.rs @@ -36,7 +36,7 @@ pub struct ProposalFees { } #[type_abi] -#[derive(TopEncode, TopDecode, NestedEncode, NestedDecode, ManagedVecItem)] +#[derive(TopEncode, TopDecode, NestedEncode, NestedDecode, ManagedVecItem, Clone)] pub struct FeeEntry { pub depositor_addr: ManagedAddress, pub tokens: EsdtTokenPayment, diff --git a/contracts/modules/src/governance/mod.rs b/contracts/modules/src/governance/mod.rs index 92eeb038db..85dfa4e1b4 100644 --- a/contracts/modules/src/governance/mod.rs +++ b/contracts/modules/src/governance/mod.rs @@ -74,7 +74,7 @@ pub trait GovernanceModule: let mut i = 0; while i < proposal.fees.entries.len() { if proposal.fees.entries.get(i).depositor_addr == caller { - fees_to_send.push(proposal.fees.entries.get(i)); + fees_to_send.push(proposal.fees.entries.get(i).clone()); proposal.fees.entries.remove(i); } else { i += 1; @@ -417,7 +417,7 @@ pub trait GovernanceModule: let payments = self.proposals().get(proposal_id).fees; for fee_entry in payments.entries.iter() { - let payment = fee_entry.tokens; + let payment = &fee_entry.tokens; self.tx() .to(&fee_entry.depositor_addr) .single_esdt( 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 d881b6a995..1d87fb2274 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 @@ -3,7 +3,7 @@ use crate::{ codec::{ multi_types::MultiValue3, DecodeErrorHandler, EncodeErrorHandler, TopDecodeMulti, TopDecodeMultiInput, TopDecodeMultiLength, TopEncodeMulti, TopEncodeMultiOutput, - }, + }, types::ManagedVecRef, }; use crate::{ @@ -42,15 +42,14 @@ impl EsdtTokenPaymentMultiValue { impl ManagedVecItem for EsdtTokenPaymentMultiValue { type PAYLOAD = as ManagedVecItem>::PAYLOAD; const SKIPS_RESERIALIZATION: bool = EsdtTokenPayment::::SKIPS_RESERIALIZATION; - type Ref<'a> = Self; + type Ref<'a> = ManagedVecRef<'a, Self>; fn read_from_payload(payload: &Self::PAYLOAD) -> Self { EsdtTokenPayment::read_from_payload(payload).into() } unsafe fn borrow_from_payload<'a>(payload: &Self::PAYLOAD) -> Self::Ref<'a> { - // TODO: managed ref - Self::read_from_payload(payload) + ManagedVecRef::new(Self::read_from_payload(payload)) } fn save_to_payload(self, payload: &mut Self::PAYLOAD) { diff --git a/framework/base/src/types/managed/wrapped.rs b/framework/base/src/types/managed/wrapped.rs index 8e3efa278f..088a250d5d 100644 --- a/framework/base/src/types/managed/wrapped.rs +++ b/framework/base/src/types/managed/wrapped.rs @@ -20,6 +20,7 @@ mod managed_vec_item; mod managed_vec_item_nested_tuple; mod managed_vec_item_payload; mod managed_vec_owned_iter; +mod managed_vec_ref; mod managed_vec_ref_iter; mod managed_vec_ref_mut; pub(crate) mod preloaded_managed_buffer; @@ -53,6 +54,7 @@ pub use managed_vec_item::{ pub use managed_vec_item_nested_tuple::ManagedVecItemNestedTuple; pub use managed_vec_item_payload::*; pub use managed_vec_owned_iter::ManagedVecOwnedIterator; +pub use managed_vec_ref::ManagedVecRef; pub use managed_vec_ref_iter::ManagedVecRefIterator; pub use managed_vec_ref_mut::ManagedVecRefMut; pub use randomness_source::RandomnessSource; 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 65ed262a41..d14ae0067f 100644 --- a/framework/base/src/types/managed/wrapped/managed_vec_item.rs +++ b/framework/base/src/types/managed/wrapped/managed_vec_item.rs @@ -13,7 +13,7 @@ use crate::{ use super::{ ManagedVecItemNestedTuple, ManagedVecItemPayload, ManagedVecItemPayloadAdd, - ManagedVecItemPayloadBuffer, + ManagedVecItemPayloadBuffer, ManagedVecRef, }; /// Types that implement this trait can be items inside a `ManagedVec`. @@ -168,7 +168,7 @@ where { type PAYLOAD = as ManagedVecItemPayloadAdd>::Output; const SKIPS_RESERIALIZATION: bool = false; - type Ref<'a> = Self; + type Ref<'a> = ManagedVecRef<'a, Self>; fn read_from_payload(payload: &Self::PAYLOAD) -> Self { let (p1, p2) = as ManagedVecItemPayloadAdd< @@ -184,7 +184,7 @@ where } unsafe fn borrow_from_payload<'a>(payload: &Self::PAYLOAD) -> Self::Ref<'a> { - Self::read_from_payload(payload) + ManagedVecRef::new(Self::read_from_payload(payload)) } fn save_to_payload(self, payload: &mut Self::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 new file mode 100644 index 0000000000..987cb60614 --- /dev/null +++ b/framework/base/src/types/managed/wrapped/managed_vec_ref.rs @@ -0,0 +1,54 @@ +use crate::types::ManagedVecItem; +use core::{borrow::Borrow, marker::PhantomData, mem::ManuallyDrop, ops::Deref}; + +pub struct ManagedVecRef<'a, T> +where + T: ManagedVecItem, +{ + _phantom: PhantomData<&'a T>, // needed for the lifetime, even though T is present + item: ManuallyDrop, +} + +impl ManagedVecRef<'_, T> +where + T: ManagedVecItem, +{ + pub unsafe fn new(item: T) -> Self { + ManagedVecRef { + _phantom: PhantomData, + item: ManuallyDrop::new(item), + } + } +} + +impl Drop for ManagedVecRef<'_, T> +where + T: ManagedVecItem, +{ + fn drop(&mut self) { + // TODO: improve + unsafe { + ManuallyDrop::drop(&mut self.item); + } + } +} + +impl Deref for ManagedVecRef<'_, T> +where + T: ManagedVecItem, +{ + type Target = T; + + fn deref(&self) -> &Self::Target { + &self.item + } +} + +impl Borrow for ManagedVecRef<'_, T> +where + T: ManagedVecItem, +{ + fn borrow(&self) -> &T { + self.deref() + } +} diff --git a/framework/derive/src/managed_vec_item_derive.rs b/framework/derive/src/managed_vec_item_derive.rs index 1531b00610..f9d7d52671 100644 --- a/framework/derive/src/managed_vec_item_derive.rs +++ b/framework/derive/src/managed_vec_item_derive.rs @@ -143,7 +143,7 @@ fn struct_derive(data_struct: &syn::DataStruct, ast: &syn::DeriveInput) -> Token impl #impl_generics multiversx_sc::types::ManagedVecItem for #name #ty_generics #where_clause { type PAYLOAD = <#payload_nested_tuple as multiversx_sc::types::ManagedVecItemNestedTuple>::PAYLOAD; const SKIPS_RESERIALIZATION: bool = #(#skips_reserialization_snippets)&&*; - type Ref<'a> = Self; + type Ref<'a> = multiversx_sc::types::ManagedVecRef<'a, Self>; fn read_from_payload(payload: &Self::PAYLOAD) -> Self { let mut index = 0; @@ -156,8 +156,7 @@ fn struct_derive(data_struct: &syn::DataStruct, ast: &syn::DeriveInput) -> Token } unsafe fn borrow_from_payload<'a>(payload: &Self::PAYLOAD) -> Self::Ref<'a> { - // TODO: managed ref - Self::read_from_payload(payload) + multiversx_sc::types::ManagedVecRef::new(Self::read_from_payload(payload)) } fn save_to_payload(self, payload: &mut Self::PAYLOAD) { From 05ddbbc97df09ae25bc6a0b9a204f71b36d21862 Mon Sep 17 00:00:00 2001 From: Andrei Marinica Date: Fri, 29 Nov 2024 15:52:27 +0200 Subject: [PATCH 3/5] ManagedVec - iterator cleanup (ref vs. owned) --- .../examples/lottery-esdt/src/lottery.rs | 2 +- .../examples/multisig/src/multisig_state.rs | 3 ++- .../examples/order-book/pair/src/common.rs | 2 +- .../examples/order-book/pair/src/events.rs | 2 +- .../seed-nft-minter/src/seed_nft_minter.rs | 2 +- .../first-contract/src/lib.rs | 4 ++-- .../forwarder-raw/src/forwarder_raw.rs | 2 +- .../composability/vault/src/vault.rs | 2 +- contracts/modules/src/staking.rs | 2 +- framework/base/src/types/heap/arg_buffer.rs | 2 +- .../types/interaction/managed_arg_buffer.rs | 2 +- .../esdt_token_payment_multi_value.rs | 3 ++- .../multi_value/multi_value_encoded.rs | 21 +++------------- .../multi_value_encoded_counted.rs | 4 ++-- .../multi_value/multi_value_managed_vec.rs | 6 +++-- .../multi_value_managed_vec_counted.rs | 6 +++-- .../src/types/managed/wrapped/managed_ref.rs | 6 ++--- .../src/types/managed/wrapped/managed_vec.rs | 9 +++---- .../managed/wrapped/managed_vec_owned_iter.rs | 24 +++++++++---------- .../types/managed/wrapped/managed_vec_ref.rs | 5 ++++ .../managed/wrapped/managed_vec_ref_iter.rs | 12 ++++++++++ .../types/managed/wrapped/traits/mergeable.rs | 2 +- framework/scenario/tests/managed_ref_test.rs | 4 ++-- 23 files changed, 68 insertions(+), 59 deletions(-) diff --git a/contracts/examples/lottery-esdt/src/lottery.rs b/contracts/examples/lottery-esdt/src/lottery.rs index 3c5d9040b1..5c573ef651 100644 --- a/contracts/examples/lottery-esdt/src/lottery.rs +++ b/contracts/examples/lottery-esdt/src/lottery.rs @@ -148,7 +148,7 @@ pub trait Lottery { if let Some(whitelist) = opt_whitelist.as_option() { let mut mapper = self.lottery_whitelist(&lottery_name); for addr in &*whitelist { - mapper.insert(addr); + mapper.insert(addr.clone()); } } diff --git a/contracts/examples/multisig/src/multisig_state.rs b/contracts/examples/multisig/src/multisig_state.rs index bfadd8efd6..bd9002f770 100644 --- a/contracts/examples/multisig/src/multisig_state.rs +++ b/contracts/examples/multisig/src/multisig_state.rs @@ -37,6 +37,7 @@ pub trait MultisigStateModule { fn add_multiple_board_members(&self, new_board_members: ManagedVec) -> usize { let mut duplicates = false; + let new_board_members_len = new_board_members.len(); self.user_mapper().get_or_create_users( new_board_members.into_iter(), |user_id, new_user| { @@ -49,7 +50,7 @@ pub trait MultisigStateModule { require!(!duplicates, "duplicate board member"); let num_board_members_mapper = self.num_board_members(); - let new_num_board_members = num_board_members_mapper.get() + new_board_members.len(); + let new_num_board_members = num_board_members_mapper.get() + new_board_members_len; num_board_members_mapper.set(new_num_board_members); new_num_board_members diff --git a/contracts/examples/order-book/pair/src/common.rs b/contracts/examples/order-book/pair/src/common.rs index 85b1c1bca8..ce28101992 100644 --- a/contracts/examples/order-book/pair/src/common.rs +++ b/contracts/examples/order-book/pair/src/common.rs @@ -8,7 +8,7 @@ pub const FREE_ORDER_FROM_STORAGE_MIN_PENALTIES: u64 = 6; #[type_abi] #[derive( - ManagedVecItem, TopEncode, TopDecode, NestedEncode, NestedDecode, PartialEq, Eq, Clone, Copy + ManagedVecItem, TopEncode, TopDecode, NestedEncode, NestedDecode, PartialEq, Eq, Clone, Copy, )] pub enum OrderType { Buy, diff --git a/contracts/examples/order-book/pair/src/events.rs b/contracts/examples/order-book/pair/src/events.rs index f20331f44f..6b66feb37d 100644 --- a/contracts/examples/order-book/pair/src/events.rs +++ b/contracts/examples/order-book/pair/src/events.rs @@ -7,7 +7,7 @@ pub trait EventsModule { fn emit_order_event(&self, order: Order) { let caller = self.blockchain().get_caller(); let epoch = self.blockchain().get_block_epoch(); - let order_type = order.order_type.clone(); + let order_type = order.order_type; self.order_event(caller, epoch, order_type, order); } diff --git a/contracts/examples/seed-nft-minter/src/seed_nft_minter.rs b/contracts/examples/seed-nft-minter/src/seed_nft_minter.rs index f0cff643c6..510212891b 100644 --- a/contracts/examples/seed-nft-minter/src/seed_nft_minter.rs +++ b/contracts/examples/seed-nft-minter/src/seed_nft_minter.rs @@ -27,7 +27,7 @@ pub trait SeedNftMinter: marketplaces: ManagedVec, distribution: ManagedVec>, ) { - self.marketplaces().extend(&marketplaces); + self.marketplaces().extend(marketplaces); self.init_distribution(distribution); } diff --git a/contracts/feature-tests/composability/esdt-contract-pair/first-contract/src/lib.rs b/contracts/feature-tests/composability/esdt-contract-pair/first-contract/src/lib.rs index 2d35ac5ea8..bf77e7ab4e 100644 --- a/contracts/feature-tests/composability/esdt-contract-pair/first-contract/src/lib.rs +++ b/contracts/feature-tests/composability/esdt-contract-pair/first-contract/src/lib.rs @@ -132,8 +132,8 @@ pub trait FirstContract { arg_buffer.push_arg(esdt_token_identifier); arg_buffer.push_arg(amount); arg_buffer.push_arg(func_name); - for arg in args.into_iter() { - arg_buffer.push_arg_raw(arg); + for arg in args { + arg_buffer.push_arg_raw(arg.clone()); } self.tx() diff --git a/contracts/feature-tests/composability/forwarder-raw/src/forwarder_raw.rs b/contracts/feature-tests/composability/forwarder-raw/src/forwarder_raw.rs index d481fd6746..a436e97b7a 100644 --- a/contracts/feature-tests/composability/forwarder-raw/src/forwarder_raw.rs +++ b/contracts/feature-tests/composability/forwarder-raw/src/forwarder_raw.rs @@ -35,7 +35,7 @@ pub trait ForwarderRaw: )); } } else { - for payment in payments.into_iter() { + for payment in payments.iter() { let _ = self.callback_payments().push(&( EgldOrEsdtTokenIdentifier::esdt(payment.token_identifier), payment.token_nonce, diff --git a/contracts/feature-tests/composability/vault/src/vault.rs b/contracts/feature-tests/composability/vault/src/vault.rs index 86ddbe31bb..37b0d65b9e 100644 --- a/contracts/feature-tests/composability/vault/src/vault.rs +++ b/contracts/feature-tests/composability/vault/src/vault.rs @@ -220,7 +220,7 @@ pub trait Vault { let mut new_tokens = ManagedVec::new(); - for payment in payments.into_iter() { + for payment in payments.iter() { // burn old tokens self.send().esdt_local_burn( &payment.token_identifier, diff --git a/contracts/modules/src/staking.rs b/contracts/modules/src/staking.rs index 7e3ce968d5..b9a76ecb01 100644 --- a/contracts/modules/src/staking.rs +++ b/contracts/modules/src/staking.rs @@ -22,7 +22,7 @@ pub trait StakingModule { user_whitelist: &ManagedVec, ) { for user in user_whitelist { - let _ = self.user_whitelist().insert(user); + let _ = self.user_whitelist().insert(user.clone()); } let nr_board_members = self.user_whitelist().len(); diff --git a/framework/base/src/types/heap/arg_buffer.rs b/framework/base/src/types/heap/arg_buffer.rs index c27be12f2c..dde5f89a06 100644 --- a/framework/base/src/types/heap/arg_buffer.rs +++ b/framework/base/src/types/heap/arg_buffer.rs @@ -91,7 +91,7 @@ where { fn from(managed_arg_buffer: &ManagedArgBuffer) -> Self { let mut result = Self::new(); - for m_arg in managed_arg_buffer.data.into_iter() { + for m_arg in &managed_arg_buffer.data { result.push_argument_bytes(m_arg.to_boxed_bytes().as_slice()); } result diff --git a/framework/base/src/types/interaction/managed_arg_buffer.rs b/framework/base/src/types/interaction/managed_arg_buffer.rs index e1b09441fc..fabe3f2c6d 100644 --- a/framework/base/src/types/interaction/managed_arg_buffer.rs +++ b/framework/base/src/types/interaction/managed_arg_buffer.rs @@ -168,7 +168,7 @@ where #[cfg(feature = "alloc")] pub fn to_raw_args_vec(&self) -> Vec> { let mut v = Vec::new(); - for item in self.data.into_iter() { + for item in &self.data { v.push(item.to_boxed_bytes().into_vec()); } v 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 1d87fb2274..e97cc2707c 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 @@ -3,7 +3,8 @@ use crate::{ codec::{ multi_types::MultiValue3, DecodeErrorHandler, EncodeErrorHandler, TopDecodeMulti, TopDecodeMultiInput, TopDecodeMultiLength, TopEncodeMulti, TopEncodeMultiOutput, - }, types::ManagedVecRef, + }, + types::ManagedVecRef, }; use crate::{ 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 a598ba9795..ca10b9ec6e 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 @@ -92,26 +92,11 @@ where try_cast_execute_or_else( v, MultiValueEncoded::from_raw_vec, - |v| MultiValueEncoded::from(&v), + MultiValueEncoded::from, ) } } -impl From<&ManagedVec> for MultiValueEncoded -where - M: ManagedTypeApi, - T: ManagedVecItem + TopEncode, -{ - #[inline] - fn from(v: &ManagedVec) -> Self { - let mut result = MultiValueEncoded::new(); - for item in v.into_iter() { - result.push(item); - } - result - } -} - impl MultiValueEncoded where M: ManagedTypeApi, @@ -181,7 +166,7 @@ where pub fn to_vec(&self) -> ManagedVec { let mut result = ManagedVec::new(); let serializer = ManagedSerializer::::new(); - for item in self.raw_buffers.into_iter() { + for item in &self.raw_buffers { result.push(serializer.top_decode_from_managed_buffer(&item)); } result @@ -198,7 +183,7 @@ where O: TopEncodeMultiOutput, H: EncodeErrorHandler, { - for elem in self.raw_buffers.into_iter() { + for elem in &self.raw_buffers { elem.multi_encode_or_handle_err(output, h)?; } Ok(()) diff --git a/framework/base/src/types/managed/multi_value/multi_value_encoded_counted.rs b/framework/base/src/types/managed/multi_value/multi_value_encoded_counted.rs index ce53008377..94b75f5fd2 100644 --- a/framework/base/src/types/managed/multi_value/multi_value_encoded_counted.rs +++ b/framework/base/src/types/managed/multi_value/multi_value_encoded_counted.rs @@ -136,7 +136,7 @@ where pub fn to_vec(&self) -> ManagedVec { let mut result = ManagedVec::new(); let serializer = ManagedSerializer::::new(); - for item in self.raw_buffers.into_iter() { + for item in &self.raw_buffers { result.push(serializer.top_decode_from_managed_buffer(&item)); } result @@ -156,7 +156,7 @@ where let raw_count = self.raw_buffers.len(); let count = raw_count / T::LEN; count.multi_encode_or_handle_err(output, h)?; - for elem in self.raw_buffers.into_iter() { + for elem in &self.raw_buffers { elem.multi_encode_or_handle_err(output, h)?; } Ok(()) diff --git a/framework/base/src/types/managed/multi_value/multi_value_managed_vec.rs b/framework/base/src/types/managed/multi_value/multi_value_managed_vec.rs index feb99b561d..e342d88cf1 100644 --- a/framework/base/src/types/managed/multi_value/multi_value_managed_vec.rs +++ b/framework/base/src/types/managed/multi_value/multi_value_managed_vec.rs @@ -1,3 +1,5 @@ +use core::borrow::Borrow; + use multiversx_sc_codec::multi_types::MultiValueVec; use crate::{ @@ -181,8 +183,8 @@ where O: TopEncodeMultiOutput, H: EncodeErrorHandler, { - for elem in self.0.into_iter() { - elem.multi_encode_or_handle_err(output, h)?; + for elem in &self.0 { + elem.borrow().multi_encode_or_handle_err(output, h)?; } Ok(()) } 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 0cb695e0d5..4f51989a9b 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 @@ -1,3 +1,5 @@ +use core::borrow::Borrow; + use crate::{ abi::{TypeAbi, TypeAbiFrom, TypeDescriptionContainer, TypeName}, api::ManagedTypeApi, @@ -122,8 +124,8 @@ where H: EncodeErrorHandler, { self.len().multi_encode_or_handle_err(output, h)?; - for elem in self.contents.into_iter() { - elem.multi_encode_or_handle_err(output, h)?; + for elem in &self.contents { + elem.borrow().multi_encode_or_handle_err(output, h)?; } Ok(()) } diff --git a/framework/base/src/types/managed/wrapped/managed_ref.rs b/framework/base/src/types/managed/wrapped/managed_ref.rs index f618063b3c..ba99ab0880 100644 --- a/framework/base/src/types/managed/wrapped/managed_ref.rs +++ b/framework/base/src/types/managed/wrapped/managed_ref.rs @@ -60,13 +60,13 @@ where } } -impl<'a, M, T> Clone for ManagedRef<'a, M, T> +impl<'a, M, T> ManagedRef<'a, M, T> where M: ManagedTypeApi, T: ManagedType, { - #[inline] - fn clone(&self) -> Self { + /// Clones the reference itself, not the object contained therein. + pub fn clone_ref(&self) -> 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 ab93734a06..ebb0f0d157 100644 --- a/framework/base/src/types/managed/wrapped/managed_vec.rs +++ b/framework/base/src/types/managed/wrapped/managed_vec.rs @@ -521,7 +521,7 @@ where fn clone(&self) -> Self { let mut result = ManagedVec::new(); for item in self.into_iter() { - result.push(item.clone()) + result.push(item.borrow().clone()) } result } @@ -611,7 +611,8 @@ where } else { let mut nested_buffer = output.start_nested_encode(); for item in self { - item.dep_encode_or_handle_err(&mut nested_buffer, h)?; + item.borrow() + .dep_encode_or_handle_err(&mut nested_buffer, h)?; } output.finalize_nested_encode(nested_buffer); Ok(()) @@ -631,7 +632,7 @@ where { self.len().dep_encode_or_handle_err(dest, h)?; for item in self { - item.dep_encode_or_handle_err(dest, h)?; + item.borrow().dep_encode_or_handle_err(dest, h)?; } Ok(()) } @@ -748,7 +749,7 @@ where fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { let mut dbg_list = f.debug_list(); for item in self.into_iter() { - dbg_list.entry(&item); + dbg_list.entry(item.borrow()); } dbg_list.finish() } diff --git a/framework/base/src/types/managed/wrapped/managed_vec_owned_iter.rs b/framework/base/src/types/managed/wrapped/managed_vec_owned_iter.rs index 8e0da8727c..b688bb466c 100644 --- a/framework/base/src/types/managed/wrapped/managed_vec_owned_iter.rs +++ b/framework/base/src/types/managed/wrapped/managed_vec_owned_iter.rs @@ -2,34 +2,34 @@ use crate::api::ManagedTypeApi; use super::{ManagedVec, ManagedVecItem, ManagedVecItemPayload}; -impl<'a, M, T> IntoIterator for &'a ManagedVec +impl IntoIterator for ManagedVec where M: ManagedTypeApi, T: ManagedVecItem, { type Item = T; - type IntoIter = ManagedVecOwnedIterator<'a, M, T>; + type IntoIter = ManagedVecOwnedIterator; fn into_iter(self) -> Self::IntoIter { ManagedVecOwnedIterator::new(self) } } -pub struct ManagedVecOwnedIterator<'a, M, T> +pub struct ManagedVecOwnedIterator where M: ManagedTypeApi, T: ManagedVecItem, { - managed_vec: &'a ManagedVec, + managed_vec: ManagedVec, byte_start: usize, byte_end: usize, } -impl<'a, M, T> ManagedVecOwnedIterator<'a, M, T> +impl ManagedVecOwnedIterator where M: ManagedTypeApi, T: ManagedVecItem, { - pub(crate) fn new(managed_vec: &'a ManagedVec) -> Self { + pub(crate) fn new(managed_vec: ManagedVec) -> Self { let byte_end = managed_vec.byte_len(); ManagedVecOwnedIterator { managed_vec, @@ -39,7 +39,7 @@ where } } -impl<'a, M, T> Iterator for ManagedVecOwnedIterator<'a, M, T> +impl Iterator for ManagedVecOwnedIterator where M: ManagedTypeApi, T: ManagedVecItem, @@ -70,14 +70,14 @@ where } } -impl<'a, M, T> ExactSizeIterator for ManagedVecOwnedIterator<'a, M, T> +impl ExactSizeIterator for ManagedVecOwnedIterator where M: ManagedTypeApi, T: ManagedVecItem, { } -impl<'a, M, T> DoubleEndedIterator for ManagedVecOwnedIterator<'a, M, T> +impl DoubleEndedIterator for ManagedVecOwnedIterator where M: ManagedTypeApi, T: ManagedVecItem, @@ -98,15 +98,15 @@ where } } -impl<'a, M, T> Clone for ManagedVecOwnedIterator<'a, M, T> +impl Clone for ManagedVecOwnedIterator where M: ManagedTypeApi, - T: ManagedVecItem, + T: ManagedVecItem + Clone, { fn clone(&self) -> Self { let byte_end = self.byte_end; Self { - managed_vec: self.managed_vec, + managed_vec: self.managed_vec.clone(), byte_start: self.byte_start, byte_end, } 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 987cb60614..de78fd5e6f 100644 --- a/framework/base/src/types/managed/wrapped/managed_vec_ref.rs +++ b/framework/base/src/types/managed/wrapped/managed_vec_ref.rs @@ -13,6 +13,11 @@ impl ManagedVecRef<'_, T> where T: ManagedVecItem, { + /// Creates a new ManagedVecRef instance. + /// + /// ## Safety + /// + /// The ManagedVecRef object might not drop its content, effectively leading to a leak. pub unsafe fn new(item: T) -> Self { ManagedVecRef { _phantom: PhantomData, diff --git a/framework/base/src/types/managed/wrapped/managed_vec_ref_iter.rs b/framework/base/src/types/managed/wrapped/managed_vec_ref_iter.rs index 4703a1f61b..9720ba741f 100644 --- a/framework/base/src/types/managed/wrapped/managed_vec_ref_iter.rs +++ b/framework/base/src/types/managed/wrapped/managed_vec_ref_iter.rs @@ -2,6 +2,18 @@ use crate::api::ManagedTypeApi; use super::{ManagedVec, ManagedVecItem, ManagedVecItemPayload}; +impl<'a, M, T> IntoIterator for &'a ManagedVec +where + M: ManagedTypeApi, + T: ManagedVecItem, +{ + type Item = T::Ref<'a>; + type IntoIter = ManagedVecRefIterator<'a, M, T>; + fn into_iter(self) -> Self::IntoIter { + ManagedVecRefIterator::new(self) + } +} + pub struct ManagedVecRefIterator<'a, M, T> where M: ManagedTypeApi, diff --git a/framework/base/src/types/managed/wrapped/traits/mergeable.rs b/framework/base/src/types/managed/wrapped/traits/mergeable.rs index 51298ba130..295357f9b6 100644 --- a/framework/base/src/types/managed/wrapped/traits/mergeable.rs +++ b/framework/base/src/types/managed/wrapped/traits/mergeable.rs @@ -21,7 +21,7 @@ pub trait Mergeable { where Self: Sized + ManagedVecItem, { - for item in &others { + for item in others { self.merge_with(item); } } diff --git a/framework/scenario/tests/managed_ref_test.rs b/framework/scenario/tests/managed_ref_test.rs index 2edfeac515..dedba7904f 100644 --- a/framework/scenario/tests/managed_ref_test.rs +++ b/framework/scenario/tests/managed_ref_test.rs @@ -16,9 +16,9 @@ where let obj_ref = obj.as_ref(); assert_eq!( obj_ref.get_handle(), - ManagedRef::get_raw_handle_of_ref(obj_ref.clone()) + ManagedRef::get_raw_handle_of_ref(obj_ref.clone_ref()) ); - let obj_clone: T = Clone::clone(&obj_ref); + let obj_clone: T = obj_ref.clone(); assert_eq!(obj, obj_clone); assert_ne!(obj_ref.get_handle(), obj_clone.get_handle()); } From 490a31c3adf3524b64a8229361d48dbedcc7d157 Mon Sep 17 00:00:00 2001 From: Andrei Marinica Date: Fri, 29 Nov 2024 17:16:08 +0200 Subject: [PATCH 4/5] stack overflow fix --- .../base/src/types/managed/multi_value/multi_value_encoded.rs | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) 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 ca10b9ec6e..e69d741f4a 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 @@ -87,12 +87,11 @@ where T: ManagedVecItem + TopEncode + 'static, { #[inline] - #[rustfmt::skip] fn from(v: ManagedVec) -> Self { try_cast_execute_or_else( v, MultiValueEncoded::from_raw_vec, - MultiValueEncoded::from, + MultiValueEncoded::from_iter, ) } } From 809b71a17ee9af5760f1d3ad83bfe6244e7a0f41 Mon Sep 17 00:00:00 2001 From: Andrei Marinica Date: Fri, 29 Nov 2024 17:49:15 +0200 Subject: [PATCH 5/5] ManagedVecItem - ref for tuples --- .../basic-features/src/echo_managed.rs | 4 ++-- .../multi_value/multi_value_managed_vec.rs | 16 +++++++++++++++- .../types/managed/wrapped/managed_vec_item.rs | 10 ++++------ 3 files changed, 21 insertions(+), 9 deletions(-) diff --git a/contracts/feature-tests/basic-features/src/echo_managed.rs b/contracts/feature-tests/basic-features/src/echo_managed.rs index ffabfa5b16..98154b2d9f 100644 --- a/contracts/feature-tests/basic-features/src/echo_managed.rs +++ b/contracts/feature-tests/basic-features/src/echo_managed.rs @@ -159,11 +159,11 @@ pub trait EchoManagedTypes { MultiValue3>>, > { let mut result = MultiValueEncoded::new(); - for triple in address_number_pairs.into_iter() { + for triple in address_number_pairs { let (address, x, counted_list) = triple.into_tuple(); let mut counted_lazy = MultiValueEncodedCounted::new(); let v = counted_list.into_vec(); - for pair in &v { + for pair in v { counted_lazy.push(pair); } result.push((address, x, counted_lazy).into()); diff --git a/framework/base/src/types/managed/multi_value/multi_value_managed_vec.rs b/framework/base/src/types/managed/multi_value/multi_value_managed_vec.rs index e342d88cf1..aa34600120 100644 --- a/framework/base/src/types/managed/multi_value/multi_value_managed_vec.rs +++ b/framework/base/src/types/managed/multi_value/multi_value_managed_vec.rs @@ -9,7 +9,7 @@ use crate::{ DecodeErrorHandler, EncodeErrorHandler, TopDecodeMulti, TopDecodeMultiInput, TopEncodeMulti, TopEncodeMultiOutput, Vec, }, - types::ManagedType, + types::{ManagedType, ManagedVecOwnedIterator}, }; use crate::types::{ManagedVec, ManagedVecItem, ManagedVecRefIterator}; @@ -144,6 +144,20 @@ where } } +impl IntoIterator for MultiValueManagedVec +where + M: ManagedTypeApi, + T: ManagedVecItem, +{ + type Item = T; + + type IntoIter = ManagedVecOwnedIterator; + + fn into_iter(self) -> Self::IntoIter { + self.0.into_iter() + } +} + impl<'a, M, T> IntoIterator for &'a MultiValueManagedVec 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 d14ae0067f..62e62ad4dd 100644 --- a/framework/base/src/types/managed/wrapped/managed_vec_item.rs +++ b/framework/base/src/types/managed/wrapped/managed_vec_item.rs @@ -324,7 +324,7 @@ where { type PAYLOAD = <(T1, (T2, ())) as ManagedVecItemNestedTuple>::PAYLOAD; const SKIPS_RESERIALIZATION: bool = T1::SKIPS_RESERIALIZATION && T2::SKIPS_RESERIALIZATION; - type Ref<'a> = Self; + type Ref<'a> = ManagedVecRef<'a, Self>; fn read_from_payload(payload: &Self::PAYLOAD) -> Self { let mut index = 0; @@ -338,8 +338,7 @@ where } unsafe fn borrow_from_payload<'a>(payload: &Self::PAYLOAD) -> Self::Ref<'a> { - // TODO: tuple of refs - Self::read_from_payload(payload) + ManagedVecRef::new(Self::read_from_payload(payload)) } fn save_to_payload(self, payload: &mut Self::PAYLOAD) { @@ -362,7 +361,7 @@ where { type PAYLOAD = <(T1, (T2, (T3, ()))) as ManagedVecItemNestedTuple>::PAYLOAD; const SKIPS_RESERIALIZATION: bool = T1::SKIPS_RESERIALIZATION && T2::SKIPS_RESERIALIZATION; - type Ref<'a> = Self; + type Ref<'a> = ManagedVecRef<'a, Self>; fn read_from_payload(payload: &Self::PAYLOAD) -> Self { let mut index = 0; @@ -377,8 +376,7 @@ where } unsafe fn borrow_from_payload<'a>(payload: &Self::PAYLOAD) -> Self::Ref<'a> { - // TODO: tuple of refs - Self::read_from_payload(payload) + ManagedVecRef::new(Self::read_from_payload(payload)) } fn save_to_payload(self, payload: &mut Self::PAYLOAD) {