From 65f9681f6773af6dc2c35df3b50abdb687bd70cc Mon Sep 17 00:00:00 2001
From: Andrei Marinica <andrei.marinica@multiversx.com>
Date: Wed, 11 Dec 2024 17:35:25 +0200
Subject: [PATCH 01/10] EndpointWrappers call_* method refactor

---
 .../tests/price_aggregator_whitebox_test.rs   | 15 ++-
 framework/derive/src/contract_impl.rs         |  8 +-
 .../derive/src/generate/endpoints_mod_gen.rs  |  4 +-
 .../derive/src/generate/function_selector.rs  | 15 ++-
 .../derive/src/generate/method_call_gen.rs    |  2 +-
 framework/derive/src/generate/snippets.rs     |  3 +-
 .../scenario/tests/contract_without_macros.rs | 97 ++++++++++++++-----
 7 files changed, 93 insertions(+), 51 deletions(-)

diff --git a/contracts/core/price-aggregator/tests/price_aggregator_whitebox_test.rs b/contracts/core/price-aggregator/tests/price_aggregator_whitebox_test.rs
index f44d9f76fc..a23edf113a 100644
--- a/contracts/core/price-aggregator/tests/price_aggregator_whitebox_test.rs
+++ b/contracts/core/price-aggregator/tests/price_aggregator_whitebox_test.rs
@@ -2,10 +2,7 @@ use multiversx_price_aggregator_sc::{
     price_aggregator_data::{OracleStatus, TimestampedPrice, TokenPair},
     PriceAggregator, MAX_ROUND_DURATION_SECONDS,
 };
-use multiversx_sc_modules::{
-    pause::EndpointWrappers as PauseEndpointWrappers,
-    staking::{EndpointWrappers as StakingEndpointWrappers, StakingModule},
-};
+use multiversx_sc_modules::{pause::PauseModule, staking::StakingModule};
 use multiversx_sc_scenario::imports::*;
 
 pub const DECIMALS: u8 = 0;
@@ -73,7 +70,7 @@ fn test_price_aggregator_submit() {
         .from(OWNER_ADDRESS)
         .to(PRICE_AGGREGATOR_ADDRESS)
         .whitebox(multiversx_price_aggregator_sc::contract_obj, |sc| {
-            sc.call_unpause_endpoint();
+            sc.unpause_endpoint();
         });
 
     // submit first timestamp too old
@@ -197,7 +194,7 @@ fn test_price_aggregator_submit_round_ok() {
         .from(OWNER_ADDRESS)
         .to(PRICE_AGGREGATOR_ADDRESS)
         .whitebox(multiversx_price_aggregator_sc::contract_obj, |sc| {
-            sc.call_unpause_endpoint();
+            sc.unpause_endpoint();
         });
 
     // submit first
@@ -304,7 +301,7 @@ fn test_price_aggregator_discarded_round() {
         .from(OWNER_ADDRESS)
         .to(PRICE_AGGREGATOR_ADDRESS)
         .whitebox(multiversx_price_aggregator_sc::contract_obj, |sc| {
-            sc.call_unpause_endpoint();
+            sc.unpause_endpoint();
         });
 
     // submit first
@@ -380,7 +377,7 @@ fn test_price_aggregator_slashing() {
         .from(OWNER_ADDRESS)
         .to(PRICE_AGGREGATOR_ADDRESS)
         .whitebox(multiversx_price_aggregator_sc::contract_obj, |sc| {
-            sc.call_unpause_endpoint();
+            sc.unpause_endpoint();
         });
 
     world
@@ -489,7 +486,7 @@ fn setup() -> (ScenarioWorld, Vec<Address>) {
             .to(PRICE_AGGREGATOR_ADDRESS)
             .egld(STAKE_AMOUNT)
             .whitebox(multiversx_price_aggregator_sc::contract_obj, |sc| {
-                sc.call_stake();
+                sc.stake();
             });
     }
 
diff --git a/framework/derive/src/contract_impl.rs b/framework/derive/src/contract_impl.rs
index 1f6b3c9383..b10d66d3ad 100644
--- a/framework/derive/src/contract_impl.rs
+++ b/framework/derive/src/contract_impl.rs
@@ -52,7 +52,7 @@ pub fn contract_implementation(
 
         impl<C> #trait_name_ident for C
         where
-        C: AutoImpl #(#supertraits_main)*
+            C: AutoImpl #(#supertraits_main)*
         {
             #(#auto_impls)*
 
@@ -75,15 +75,15 @@ pub fn contract_implementation(
         {
             #(#call_methods)*
 
-            fn call(&self, fn_name: &str) -> bool {
+            fn call(&mut self, fn_name: &str) -> bool {
                 #function_selector_body
             }
 
-            fn callback_selector(&self, mut ___cb_closure___: multiversx_sc::types::CallbackClosureForDeser<Self::Api>) -> multiversx_sc::types::CallbackSelectorResult<Self::Api> {
+            fn callback_selector(&mut self, mut ___cb_closure___: multiversx_sc::types::CallbackClosureForDeser<Self::Api>) -> multiversx_sc::types::CallbackSelectorResult<Self::Api> {
                 #callback_selector_body
             }
 
-            fn callback(&self) {
+            fn callback(&mut self) {
                 #callback_body
             }
         }
diff --git a/framework/derive/src/generate/endpoints_mod_gen.rs b/framework/derive/src/generate/endpoints_mod_gen.rs
index 4bba840a90..e30ac37604 100644
--- a/framework/derive/src/generate/endpoints_mod_gen.rs
+++ b/framework/derive/src/generate/endpoints_mod_gen.rs
@@ -37,7 +37,7 @@ pub fn generate_endpoints_mod(
                 A: multiversx_sc::api::VMApi ,
             {
                 super::EndpointWrappers::callback(
-                    &multiversx_sc::contract_base::UniversalContractObj::<A>::new(),
+                    &mut multiversx_sc::contract_base::UniversalContractObj::<A>::new(),
                 );
             }
         }
@@ -93,7 +93,7 @@ fn generate_wasm_endpoint(
             A: multiversx_sc::api::VMApi,
         {
             super::EndpointWrappers::#call_method_ident(
-                &multiversx_sc::contract_base::UniversalContractObj::<A>::new(),
+                &mut multiversx_sc::contract_base::UniversalContractObj::<A>::new(),
             );
         }
     }
diff --git a/framework/derive/src/generate/function_selector.rs b/framework/derive/src/generate/function_selector.rs
index 6f157724f8..3aed56f622 100644
--- a/framework/derive/src/generate/function_selector.rs
+++ b/framework/derive/src/generate/function_selector.rs
@@ -48,21 +48,20 @@ pub fn generate_function_selector_body(contract: &ContractTrait) -> proc_macro2:
     let module_calls =
         supertrait_gen::function_selector_module_calls(contract.supertraits.as_slice());
     quote! {
-        if match fn_name {
+        match fn_name {
             "callBack" => {
                 self::EndpointWrappers::callback(self);
-                return true;
+                true
             },
             "init" if <Self::Api as multiversx_sc::api::VMApi>::external_view_init_override() => {
                 multiversx_sc::external_view_contract::external_view_contract_constructor::<Self::Api>();
-                return true;
+                true
             },
             #(#match_arms)*
-            other => false
-        } {
-            return true;
+            other => {
+                #(#module_calls)*
+                false
+            }
         }
-        #(#module_calls)*
-        false
     }
 }
diff --git a/framework/derive/src/generate/method_call_gen.rs b/framework/derive/src/generate/method_call_gen.rs
index a34db90f06..74d3f3ce4f 100644
--- a/framework/derive/src/generate/method_call_gen.rs
+++ b/framework/derive/src/generate/method_call_gen.rs
@@ -27,7 +27,7 @@ pub fn generate_call_method(m: &Method) -> proc_macro2::TokenStream {
     let call_method_body = generate_endpoint_call_method_body(m);
     quote! {
         #[inline]
-        fn #call_method_ident (&self) {
+        fn #call_method_ident (&mut self) {
             #call_method_body
         }
     }
diff --git a/framework/derive/src/generate/snippets.rs b/framework/derive/src/generate/snippets.rs
index 6e66eb9ae4..91fc8a863f 100644
--- a/framework/derive/src/generate/snippets.rs
+++ b/framework/derive/src/generate/snippets.rs
@@ -67,7 +67,8 @@ pub fn impl_callable_contract() -> proc_macro2::TokenStream {
             A: multiversx_sc::api::VMApi + Send + Sync,
         {
             fn call(&self, fn_name: &str) -> bool {
-                EndpointWrappers::call(self, fn_name)
+                let mut obj = multiversx_sc::contract_base::UniversalContractObj::<A>::new();
+                EndpointWrappers::call(&mut obj, fn_name)
             }
         }
     }
diff --git a/framework/scenario/tests/contract_without_macros.rs b/framework/scenario/tests/contract_without_macros.rs
index c597bb9e81..ccdcc493fd 100644
--- a/framework/scenario/tests/contract_without_macros.rs
+++ b/framework/scenario/tests/contract_without_macros.rs
@@ -9,7 +9,7 @@
 #![allow(unused)]
 
 use multiversx_sc::{
-    contract_base::ProxyObjNew,
+    contract_base::{CallableContractBuilder, ProxyObjNew},
     types::{BigInt, ManagedAddress},
 };
 use multiversx_sc_scenario::api::{SingleTxApi, StaticApi};
@@ -57,19 +57,19 @@ mod module_1 {
 
     pub trait EndpointWrappers: VersionModule + multiversx_sc::contract_base::ContractBase {
         #[inline]
-        fn call_version(&self) {
+        fn call_version(&mut self) {
             multiversx_sc::io::call_value_init::not_payable::<Self::Api>();
             let result = self.version();
             multiversx_sc::io::finish_multi::<Self::Api, _>(&result)
         }
 
-        fn call_some_async(&self) {
+        fn call_some_async(&mut self) {
             self.some_async();
             multiversx_sc::io::finish_multi::<Self::Api, _>(&())
         }
 
-        fn call(&self, fn_name: &str) -> bool {
-            if match fn_name {
+        fn call(&mut self, fn_name: &str) -> bool {
+            match fn_name {
                 "callBack" => {
                     self.callback();
                     return true;
@@ -79,10 +79,13 @@ mod module_1 {
                     true
                 },
                 _other => false,
-            } {
-                return true;
             }
-            false
+        }
+        fn callback_selector(
+            &mut self,
+            mut ___cb_closure___: multiversx_sc::types::CallbackClosureForDeser<Self::Api>,
+        ) -> multiversx_sc::types::CallbackSelectorResult<Self::Api> {
+            multiversx_sc::types::CallbackSelectorResult::NotProcessed(___cb_closure___)
         }
     }
 
@@ -277,7 +280,7 @@ mod sample_adder {
         Adder + multiversx_sc::contract_base::ContractBase + super::module_1::EndpointWrappers
     {
         #[inline]
-        fn call_sum(&self) {
+        fn call_sum(&mut self) {
             <Self::Api as multiversx_sc::api::VMApi>::init_static();
             multiversx_sc::io::call_value_init::not_payable::<Self::Api>();
             let () = multiversx_sc::io::load_endpoint_args::<Self::Api, ()>(());
@@ -285,7 +288,7 @@ mod sample_adder {
             multiversx_sc::io::finish_multi::<Self::Api, _>(&result);
         }
         #[inline]
-        fn call_init(&self) {
+        fn call_init(&mut self) {
             <Self::Api as multiversx_sc::api::VMApi>::init_static();
             multiversx_sc::io::call_value_init::not_payable::<Self::Api>();
             let (initial_value, ()) = multiversx_sc::io::load_endpoint_args::<
@@ -295,7 +298,7 @@ mod sample_adder {
             self.init(initial_value);
         }
         #[inline]
-        fn call_upgrade(&self) {
+        fn call_upgrade(&mut self) {
             <Self::Api as multiversx_sc::api::VMApi>::init_static();
             multiversx_sc::io::call_value_init::not_payable::<Self::Api>();
             let (initial_value, ()) = multiversx_sc::io::load_endpoint_args::<
@@ -305,7 +308,7 @@ mod sample_adder {
             self.upgrade(initial_value);
         }
         #[inline]
-        fn call_add(&self) {
+        fn call_add(&mut self) {
             <Self::Api as multiversx_sc::api::VMApi>::init_static();
             multiversx_sc::io::call_value_init::not_payable::<Self::Api>();
             let (value, ()) = multiversx_sc::io::load_endpoint_args::<
@@ -314,8 +317,8 @@ mod sample_adder {
             >(("value", ()));
             self.add(value);
         }
-        fn call(&self, fn_name: &str) -> bool {
-            if match fn_name {
+        fn call(&mut self, fn_name: &str) -> bool {
+            match fn_name {
                 "callBack" => {
                     self::EndpointWrappers::callback(self);
                     return true;
@@ -346,19 +349,58 @@ mod sample_adder {
                     self.call_add();
                     true
                 },
-                other => false,
-            } {
-                return true;
+                other => {
+                    if super::module_1::EndpointWrappers::call(self, fn_name) {
+                        return true;
+                    }
+                    false
+                },
             }
-            false
         }
         fn callback_selector(
-            &self,
+            &mut self,
             mut ___cb_closure___: multiversx_sc::types::CallbackClosureForDeser<Self::Api>,
         ) -> multiversx_sc::types::CallbackSelectorResult<Self::Api> {
+            let ___cb_closure_matcher___ = ___cb_closure___.matcher::<32usize>();
+            if ___cb_closure_matcher___.matches_empty() {
+                return multiversx_sc::types::CallbackSelectorResult::Processed;
+            }
+            match super::module_1::EndpointWrappers::callback_selector(self, ___cb_closure___) {
+                multiversx_sc::types::CallbackSelectorResult::Processed => {
+                    return multiversx_sc::types::CallbackSelectorResult::Processed;
+                },
+                multiversx_sc::types::CallbackSelectorResult::NotProcessed(
+                    recovered_cb_closure,
+                ) => {
+                    ___cb_closure___ = recovered_cb_closure;
+                },
+            }
+            match super::module_1::EndpointWrappers::callback_selector(self, ___cb_closure___) {
+                multiversx_sc::types::CallbackSelectorResult::Processed => {
+                    return multiversx_sc::types::CallbackSelectorResult::Processed;
+                },
+                multiversx_sc::types::CallbackSelectorResult::NotProcessed(
+                    recovered_cb_closure,
+                ) => {
+                    ___cb_closure___ = recovered_cb_closure;
+                },
+            }
             multiversx_sc::types::CallbackSelectorResult::NotProcessed(___cb_closure___)
         }
-        fn callback(&self) {}
+        fn callback(&mut self) {
+            if let Some(___cb_closure___) =
+                multiversx_sc::types::CallbackClosureForDeser::storage_load_and_clear::<Self::Api>()
+            {
+                if let multiversx_sc::types::CallbackSelectorResult::NotProcessed(_) =
+                    self::EndpointWrappers::callback_selector(self, ___cb_closure___)
+                {
+                    multiversx_sc::api::ErrorApiImpl::signal_error(
+                        &<Self::Api as multiversx_sc::api::ErrorApi>::error_api_impl(),
+                        err_msg::CALLBACK_BAD_FUNC.as_bytes(),
+                    );
+                }
+            }
+        }
     }
 
     impl<A> EndpointWrappers for multiversx_sc::contract_base::UniversalContractObj<A> where
@@ -441,7 +483,7 @@ mod sample_adder {
             A: multiversx_sc::api::VMApi,
         {
             super::EndpointWrappers::call_sum(
-                &multiversx_sc::contract_base::UniversalContractObj::<A>::new(),
+                &mut multiversx_sc::contract_base::UniversalContractObj::<A>::new(),
             );
         }
         pub fn init<A>()
@@ -449,7 +491,7 @@ mod sample_adder {
             A: multiversx_sc::api::VMApi,
         {
             super::EndpointWrappers::call_init(
-                &multiversx_sc::contract_base::UniversalContractObj::<A>::new(),
+                &mut multiversx_sc::contract_base::UniversalContractObj::<A>::new(),
             );
         }
         pub fn upgrade<A>()
@@ -457,7 +499,7 @@ mod sample_adder {
             A: multiversx_sc::api::VMApi,
         {
             super::EndpointWrappers::call_upgrade(
-                &multiversx_sc::contract_base::UniversalContractObj::<A>::new(),
+                &mut multiversx_sc::contract_base::UniversalContractObj::<A>::new(),
             );
         }
         pub fn add<A>()
@@ -465,7 +507,7 @@ mod sample_adder {
             A: multiversx_sc::api::VMApi,
         {
             super::EndpointWrappers::call_add(
-                &multiversx_sc::contract_base::UniversalContractObj::<A>::new(),
+                &mut multiversx_sc::contract_base::UniversalContractObj::<A>::new(),
             );
         }
         pub fn callBack<A>()
@@ -473,7 +515,7 @@ mod sample_adder {
             A: multiversx_sc::api::VMApi,
         {
             super::EndpointWrappers::callback(
-                &multiversx_sc::contract_base::UniversalContractObj::<A>::new(),
+                &mut multiversx_sc::contract_base::UniversalContractObj::<A>::new(),
             );
         }
     }
@@ -597,7 +639,8 @@ mod sample_adder {
         A: multiversx_sc::api::VMApi,
     {
         fn call(&self, fn_name: &str) -> bool {
-            EndpointWrappers::call(self, fn_name)
+            let mut obj = multiversx_sc::contract_base::UniversalContractObj::<A>::new();
+            EndpointWrappers::call(&mut obj, fn_name)
         }
     }
 
@@ -770,8 +813,10 @@ fn contract_without_macros_basic() {
 
     assert_eq!(BigInt::from(100), adder.version());
 
+    let adder = sample_adder::ContractBuilder.new_contract_obj::<SingleTxApi>();
     assert!(!adder.call("invalid_endpoint"));
 
+    let adder = sample_adder::ContractBuilder.new_contract_obj::<SingleTxApi>();
     assert!(adder.call("getSum"));
 
     let mut own_proxy =

From de3b6df1fa6ebabc69c8eefb34a38c390f738941 Mon Sep 17 00:00:00 2001
From: Andrei Marinica <andrei.marinica@multiversx.com>
Date: Wed, 11 Dec 2024 18:25:56 +0200
Subject: [PATCH 02/10] cleanup, comments

---
 framework/scenario/tests/contract_without_macros.rs | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/framework/scenario/tests/contract_without_macros.rs b/framework/scenario/tests/contract_without_macros.rs
index ccdcc493fd..d461adea6d 100644
--- a/framework/scenario/tests/contract_without_macros.rs
+++ b/framework/scenario/tests/contract_without_macros.rs
@@ -254,8 +254,6 @@ mod sample_adder {
     /////////////////////////////////////////////////////////////////////////////////////////////////
     pub trait AutoImpl: multiversx_sc::contract_base::ContractBase {}
 
-    // impl<C> super::module_1::AutoImpl for C where C: AutoImpl {}
-
     impl<C> Adder for C
     where
         C: AutoImpl + super::module_1::AutoImpl,
@@ -639,6 +637,8 @@ mod sample_adder {
         A: multiversx_sc::api::VMApi,
     {
         fn call(&self, fn_name: &str) -> bool {
+            // creating a new object, which we can mutate
+            // because of dynamic traits, we cannot move `self`
             let mut obj = multiversx_sc::contract_base::UniversalContractObj::<A>::new();
             EndpointWrappers::call(&mut obj, fn_name)
         }

From 81f28d55bc1d465e0abafa33e2181fa4368543ea Mon Sep 17 00:00:00 2001
From: Andrei Marinica <andrei.marinica@multiversx.com>
Date: Wed, 11 Dec 2024 20:34:09 +0200
Subject: [PATCH 03/10] refactor: ManagedResultArgLoader replaced with
 ManagedVec iterators

---
 .../contract_call_legacy/contract_deploy.rs   |  4 +--
 .../base/src/types/interaction/tx_exec.rs     |  4 +--
 .../multi_value/multi_value_encoded_iter.rs   | 23 +++++++------
 .../managed/wrapped/managed_vec_iter_owned.rs | 33 ++++++++++++++++++-
 .../wrapped/managed_vec_iter_payload.rs       | 21 +++++++++---
 .../managed/wrapped/managed_vec_iter_ref.rs   | 33 ++++++++++++++++++-
 6 files changed, 95 insertions(+), 23 deletions(-)

diff --git a/framework/base/src/types/interaction/contract_call_legacy/contract_deploy.rs b/framework/base/src/types/interaction/contract_call_legacy/contract_deploy.rs
index 6b19010e3d..8b12548b30 100644
--- a/framework/base/src/types/interaction/contract_call_legacy/contract_deploy.rs
+++ b/framework/base/src/types/interaction/contract_call_legacy/contract_deploy.rs
@@ -9,7 +9,7 @@ use crate::{
     api::{BlockchainApiImpl, CallTypeApi},
     contract_base::{ExitCodecErrorHandler, SendRawWrapper},
     err_msg,
-    io::{ArgErrorHandler, ArgId, ManagedResultArgLoader},
+    io::{ArgErrorHandler, ArgId},
     types::{
         BigUint, CodeMetadata, ManagedAddress, ManagedArgBuffer, ManagedBuffer, ManagedOption,
         ManagedVec,
@@ -112,7 +112,7 @@ where
     where
         RequestedResult: TopDecodeMulti + TypeAbiFrom<OriginalResult>,
     {
-        let mut loader = ManagedResultArgLoader::new(raw_result);
+        let mut loader = raw_result.into_iter();
         let arg_id = ArgId::from(&b"init result"[..]);
         let h = ArgErrorHandler::<SA>::from(arg_id);
         RequestedResult::multi_decode_or_handle_err(&mut loader, h).unwrap_infallible()
diff --git a/framework/base/src/types/interaction/tx_exec.rs b/framework/base/src/types/interaction/tx_exec.rs
index 0c200df330..6f4ffc40d3 100644
--- a/framework/base/src/types/interaction/tx_exec.rs
+++ b/framework/base/src/types/interaction/tx_exec.rs
@@ -15,7 +15,7 @@ use unwrap_infallible::UnwrapInfallible;
 
 use crate::{
     api::CallTypeApi,
-    io::{ArgErrorHandler, ArgId, ManagedResultArgLoader},
+    io::{ArgErrorHandler, ArgId},
     types::{ManagedBuffer, ManagedVec},
 };
 use multiversx_sc_codec::TopDecodeMulti;
@@ -30,7 +30,7 @@ where
     SA: CallTypeApi + 'static,
     RequestedResult: TopDecodeMulti,
 {
-    let mut loader = ManagedResultArgLoader::new(raw_result);
+    let mut loader = raw_result.into_iter();
     let arg_id = ArgId::from(&b"sync result"[..]);
     let h: ArgErrorHandler<SA> = ArgErrorHandler::<SA>::from(arg_id);
     RequestedResult::multi_decode_or_handle_err(&mut loader, h).unwrap_infallible()
diff --git a/framework/base/src/types/managed/multi_value/multi_value_encoded_iter.rs b/framework/base/src/types/managed/multi_value/multi_value_encoded_iter.rs
index 4b8db58ffb..670586fbf6 100644
--- a/framework/base/src/types/managed/multi_value/multi_value_encoded_iter.rs
+++ b/framework/base/src/types/managed/multi_value/multi_value_encoded_iter.rs
@@ -4,10 +4,10 @@ use unwrap_infallible::UnwrapInfallible;
 
 use crate::codec::{TopDecodeMulti, TopDecodeMultiInput};
 
-use crate::types::{ManagedBuffer, ManagedVec};
+use crate::types::{ManagedBuffer, ManagedVec, ManagedVecOwnedIterator};
 use crate::{
     api::{ErrorApi, ManagedTypeApi},
-    io::{ArgErrorHandler, ArgId, ManagedResultArgLoader},
+    io::{ArgErrorHandler, ArgId},
 };
 
 /// Iterator for `MultiValueEncoded` and `MultiValueEncodedCounted`.
@@ -18,7 +18,7 @@ where
     M: ManagedTypeApi + ErrorApi,
     T: TopDecodeMulti,
 {
-    data_loader: ManagedResultArgLoader<M>,
+    data_loader: ManagedVecOwnedIterator<M, ManagedBuffer<M>>,
     _phantom: PhantomData<T>,
 }
 
@@ -29,7 +29,7 @@ where
 {
     pub(crate) fn new(raw_buffers: ManagedVec<M, ManagedBuffer<M>>) -> Self {
         MultiValueEncodedIterator {
-            data_loader: ManagedResultArgLoader::new(raw_buffers),
+            data_loader: raw_buffers.into_iter(),
             _phantom: PhantomData,
         }
     }
@@ -43,14 +43,13 @@ where
     type Item = T;
 
     fn next(&mut self) -> Option<T> {
-        if self.data_loader.has_next() {
-            let arg_id = ArgId::from(&b"var args"[..]);
-            let h = ArgErrorHandler::<M>::from(arg_id);
-            let result =
-                T::multi_decode_or_handle_err(&mut self.data_loader, h).unwrap_infallible();
-            Some(result)
-        } else {
-            None
+        if !self.data_loader.has_next() {
+            return None;
         }
+
+        let arg_id = ArgId::from(&b"var args"[..]);
+        let h = ArgErrorHandler::<M>::from(arg_id);
+        let result = T::multi_decode_or_handle_err(&mut self.data_loader, h).unwrap_infallible();
+        Some(result)
     }
 }
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 055b4b4a11..f4712e7464 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
@@ -1,4 +1,9 @@
-use crate::{api::ManagedTypeApi, types::ManagedType};
+use multiversx_sc_codec::{DecodeError, DecodeErrorHandler, TopDecodeMultiInput};
+
+use crate::{
+    api::{ErrorApi, ManagedTypeApi},
+    types::{ManagedBuffer, ManagedType},
+};
 
 use super::{ManagedVec, ManagedVecItem, ManagedVecPayloadIterator};
 
@@ -34,6 +39,10 @@ where
             }
         }
     }
+
+    pub(crate) fn iter_is_empty(&self) -> bool {
+        self.payload_iter.iter_is_empty()
+    }
 }
 
 impl<M, T> Iterator for ManagedVecOwnedIterator<M, T>
@@ -70,3 +79,25 @@ where
         Some(T::read_from_payload(&payload))
     }
 }
+
+impl<A> TopDecodeMultiInput for ManagedVecOwnedIterator<A, ManagedBuffer<A>>
+where
+    A: ManagedTypeApi + ErrorApi,
+{
+    type ValueInput = ManagedBuffer<A>;
+
+    fn has_next(&self) -> bool {
+        !self.iter_is_empty()
+    }
+
+    fn next_value_input<H>(&mut self, h: H) -> Result<Self::ValueInput, H::HandledErr>
+    where
+        H: DecodeErrorHandler,
+    {
+        if let Some(buffer) = self.next() {
+            Ok(buffer)
+        } else {
+            Err(h.handle_error(DecodeError::MULTI_TOO_FEW_ARGS))
+        }
+    }
+}
diff --git a/framework/base/src/types/managed/wrapped/managed_vec_iter_payload.rs b/framework/base/src/types/managed/wrapped/managed_vec_iter_payload.rs
index 44293133d2..28fd6e3943 100644
--- a/framework/base/src/types/managed/wrapped/managed_vec_iter_payload.rs
+++ b/framework/base/src/types/managed/wrapped/managed_vec_iter_payload.rs
@@ -40,6 +40,15 @@ where
             _phantom: PhantomData,
         }
     }
+
+    pub(crate) fn remaining(&self) -> usize {
+        (self.byte_end - self.byte_start) / P::payload_size()
+    }
+
+    /// TODO: can be replaced with ExactSizeIterator::is_empty once it's stabilized
+    pub(crate) fn iter_is_empty(&self) -> bool {
+        self.byte_start >= self.byte_end
+    }
 }
 
 impl<M, P> Iterator for ManagedVecPayloadIterator<M, P>
@@ -50,10 +59,10 @@ where
     type Item = P;
 
     fn next(&mut self) -> Option<P> {
-        let next_byte_start = self.byte_start + P::payload_size();
-        if next_byte_start > self.byte_end {
+        if self.iter_is_empty() {
             return None;
         }
+        let next_byte_start = self.byte_start + P::payload_size();
 
         let mut payload = P::new_buffer();
         let _ = M::managed_type_impl().mb_load_slice(
@@ -67,8 +76,7 @@ where
     }
 
     fn size_hint(&self) -> (usize, Option<usize>) {
-        let size = P::payload_size();
-        let remaining = (self.byte_end - self.byte_start) / size;
+        let remaining = self.remaining();
         (remaining, Some(remaining))
     }
 }
@@ -78,6 +86,9 @@ where
     M: ManagedTypeApi,
     P: ManagedVecItemPayload,
 {
+    fn len(&self) -> usize {
+        self.remaining()
+    }
 }
 
 impl<M, P> DoubleEndedIterator for ManagedVecPayloadIterator<M, P>
@@ -86,7 +97,7 @@ where
     P: ManagedVecItemPayload,
 {
     fn next_back(&mut self) -> Option<Self::Item> {
-        if self.byte_start + P::payload_size() > self.byte_end {
+        if self.iter_is_empty() {
             return None;
         }
         self.byte_end -= P::payload_size();
diff --git a/framework/base/src/types/managed/wrapped/managed_vec_iter_ref.rs b/framework/base/src/types/managed/wrapped/managed_vec_iter_ref.rs
index b57a16d3d7..7305462b1c 100644
--- a/framework/base/src/types/managed/wrapped/managed_vec_iter_ref.rs
+++ b/framework/base/src/types/managed/wrapped/managed_vec_iter_ref.rs
@@ -1,6 +1,11 @@
 use core::marker::PhantomData;
 
-use crate::{api::ManagedTypeApi, types::ManagedType};
+use multiversx_sc_codec::{DecodeError, DecodeErrorHandler, TopDecodeMultiInput};
+
+use crate::{
+    api::{ErrorApi, ManagedTypeApi},
+    types::{ManagedBuffer, ManagedType},
+};
 
 use super::{ManagedVec, ManagedVecItem, ManagedVecPayloadIterator};
 
@@ -38,6 +43,10 @@ where
             }
         }
     }
+
+    pub(crate) fn iter_is_empty(&self) -> bool {
+        self.payload_iter.iter_is_empty()
+    }
 }
 
 impl<'a, M, T> Iterator for ManagedVecRefIterator<'a, M, T>
@@ -89,3 +98,25 @@ where
         }
     }
 }
+
+impl<'a, A> TopDecodeMultiInput for ManagedVecRefIterator<'a, A, ManagedBuffer<A>>
+where
+    A: ManagedTypeApi + ErrorApi,
+{
+    type ValueInput = ManagedBuffer<A>;
+
+    fn has_next(&self) -> bool {
+        !self.iter_is_empty()
+    }
+
+    fn next_value_input<H>(&mut self, h: H) -> Result<Self::ValueInput, H::HandledErr>
+    where
+        H: DecodeErrorHandler,
+    {
+        if let Some(buffer) = self.next() {
+            Ok(buffer.clone())
+        } else {
+            Err(h.handle_error(DecodeError::MULTI_TOO_FEW_ARGS))
+        }
+    }
+}

From 2e776b7b56f1a579fc776294d1bb2612d02103be Mon Sep 17 00:00:00 2001
From: Andrei Marinica <andrei.marinica@multiversx.com>
Date: Wed, 11 Dec 2024 20:41:15 +0200
Subject: [PATCH 04/10] clippy fix

---
 .../base/src/types/managed/wrapped/managed_vec_iter_ref.rs      | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/framework/base/src/types/managed/wrapped/managed_vec_iter_ref.rs b/framework/base/src/types/managed/wrapped/managed_vec_iter_ref.rs
index 7305462b1c..ae5212c9d5 100644
--- a/framework/base/src/types/managed/wrapped/managed_vec_iter_ref.rs
+++ b/framework/base/src/types/managed/wrapped/managed_vec_iter_ref.rs
@@ -99,7 +99,7 @@ where
     }
 }
 
-impl<'a, A> TopDecodeMultiInput for ManagedVecRefIterator<'a, A, ManagedBuffer<A>>
+impl<A> TopDecodeMultiInput for ManagedVecRefIterator<'_, A, ManagedBuffer<A>>
 where
     A: ManagedTypeApi + ErrorApi,
 {

From 7955fcc41e3c9e6c07b12a439907607458534a23 Mon Sep 17 00:00:00 2001
From: Andrei Marinica <andrei.marinica@multiversx.com>
Date: Wed, 11 Dec 2024 20:41:43 +0200
Subject: [PATCH 05/10] refactor: ManagedResultArgLoader replaced in legacy
 callback

---
 framework/base/src/types/interaction/callback_closure.rs | 7 +++----
 framework/derive/src/generate/method_call_gen_arg.rs     | 2 +-
 2 files changed, 4 insertions(+), 5 deletions(-)

diff --git a/framework/base/src/types/interaction/callback_closure.rs b/framework/base/src/types/interaction/callback_closure.rs
index 6b2b73feee..b7ea4264a8 100644
--- a/framework/base/src/types/interaction/callback_closure.rs
+++ b/framework/base/src/types/interaction/callback_closure.rs
@@ -9,10 +9,9 @@ use crate::{
     },
     contract_base::{BlockchainWrapper, ExitCodecErrorHandler, ManagedSerializer},
     err_msg,
-    io::ManagedResultArgLoader,
     storage::StorageKey,
     storage_clear, storage_get, storage_set,
-    types::{ManagedBuffer, ManagedType},
+    types::{ManagedBuffer, ManagedType, ManagedVecRefIterator},
 };
 
 use super::ManagedArgBuffer;
@@ -125,8 +124,8 @@ impl<M: ManagedTypeApi + ErrorApi> CallbackClosureForDeser<M> {
         CallbackClosureMatcher::new(&self.callback_name)
     }
 
-    pub fn into_arg_loader(self) -> ManagedResultArgLoader<M> {
-        ManagedResultArgLoader::new(self.closure_args.data)
+    pub fn arg_iter(&self) -> ManagedVecRefIterator<'_, M, ManagedBuffer<M>> {
+        self.closure_args.iter_buffers()
     }
 }
 
diff --git a/framework/derive/src/generate/method_call_gen_arg.rs b/framework/derive/src/generate/method_call_gen_arg.rs
index 20550ca024..8c9b7a0aee 100644
--- a/framework/derive/src/generate/method_call_gen_arg.rs
+++ b/framework/derive/src/generate/method_call_gen_arg.rs
@@ -88,7 +88,7 @@ pub fn load_legacy_cb_closure_args_snippet(m: &Method) -> proc_macro2::TokenStre
         });
     quote! {
         let #closure_var_names = multiversx_sc::io::load_multi_args_custom_loader::<Self::Api, _, #closure_var_types>(
-            ___cb_closure___.into_arg_loader(),
+            ___cb_closure___.arg_iter(),
             #closure_var_names_str,
         );
     }

From d74aa6add2e85e36adb924da075b2ebd9a3ac4df Mon Sep 17 00:00:00 2001
From: Andrei Marinica <andrei.marinica@multiversx.com>
Date: Wed, 11 Dec 2024 21:08:42 +0200
Subject: [PATCH 06/10] simplified callback_selector

---
 .../interaction/callback_selector_result.rs   | 18 ++++-----
 framework/derive/src/contract_impl.rs         |  4 +-
 framework/derive/src/generate/callback_gen.rs | 18 +++------
 .../scenario/tests/contract_without_macros.rs | 39 ++++++-------------
 4 files changed, 30 insertions(+), 49 deletions(-)

diff --git a/framework/base/src/types/interaction/callback_selector_result.rs b/framework/base/src/types/interaction/callback_selector_result.rs
index d04487b57f..e6bd200a66 100644
--- a/framework/base/src/types/interaction/callback_selector_result.rs
+++ b/framework/base/src/types/interaction/callback_selector_result.rs
@@ -1,13 +1,13 @@
-use crate::api::{ErrorApi, ManagedTypeApi};
-
-use super::CallbackClosureForDeser;
-
 /// Used internally between the `callback` and `callback_selector` methods.
 /// It is likely to be removed in the future.
-pub enum CallbackSelectorResult<A>
-where
-    A: ManagedTypeApi + ErrorApi,
-{
+#[derive(Clone, Copy, PartialEq, Eq)]
+pub enum CallbackSelectorResult {
     Processed,
-    NotProcessed(CallbackClosureForDeser<A>),
+    NotProcessed,
+}
+
+impl CallbackSelectorResult {
+    pub fn is_processed(self) -> bool {
+        matches!(self, CallbackSelectorResult::Processed)
+    }
 }
diff --git a/framework/derive/src/contract_impl.rs b/framework/derive/src/contract_impl.rs
index b10d66d3ad..32ee2d76e0 100644
--- a/framework/derive/src/contract_impl.rs
+++ b/framework/derive/src/contract_impl.rs
@@ -79,7 +79,9 @@ pub fn contract_implementation(
                 #function_selector_body
             }
 
-            fn callback_selector(&mut self, mut ___cb_closure___: multiversx_sc::types::CallbackClosureForDeser<Self::Api>) -> multiversx_sc::types::CallbackSelectorResult<Self::Api> {
+            fn callback_selector(&mut self, ___cb_closure___: &multiversx_sc::types::CallbackClosureForDeser<Self::Api>)
+                -> multiversx_sc::types::CallbackSelectorResult
+            {
                 #callback_selector_body
             }
 
diff --git a/framework/derive/src/generate/callback_gen.rs b/framework/derive/src/generate/callback_gen.rs
index 23a3a56713..e16e6daafa 100644
--- a/framework/derive/src/generate/callback_gen.rs
+++ b/framework/derive/src/generate/callback_gen.rs
@@ -29,7 +29,7 @@ pub fn generate_callback_selector_and_main(
         let cb_main_body = quote! {
             let _ = self::EndpointWrappers::callback_selector(
                 self,
-                multiversx_sc::types::CallbackClosureForDeser::no_callback(),
+                &multiversx_sc::types::CallbackClosureForDeser::no_callback(),
             );
         };
         (cb_selector_body, cb_main_body)
@@ -39,7 +39,7 @@ pub fn generate_callback_selector_and_main(
             module_calls(contract.supertraits.as_slice());
         if match_arms.is_empty() && module_calls.is_empty() {
             let cb_selector_body = quote! {
-                multiversx_sc::types::CallbackSelectorResult::NotProcessed(___cb_closure___)
+                multiversx_sc::types::CallbackSelectorResult::NotProcessed
             };
             let cb_main_body = quote! {};
             (cb_selector_body, cb_main_body)
@@ -47,8 +47,7 @@ pub fn generate_callback_selector_and_main(
             let cb_selector_body = callback_selector_body(match_arms, module_calls);
             let cb_main_body = quote! {
                 if let Some(___cb_closure___) = multiversx_sc::types::CallbackClosureForDeser::storage_load_and_clear::<Self::Api>() {
-                    if let multiversx_sc::types::CallbackSelectorResult::NotProcessed(_) =
-                        self::EndpointWrappers::callback_selector(self, ___cb_closure___) {
+                    if !self::EndpointWrappers::callback_selector(self, &___cb_closure___).is_processed() {
                         multiversx_sc::api::ErrorApiImpl::signal_error(
                             &<Self::Api as multiversx_sc::api::ErrorApi>::error_api_impl(),
                             err_msg::CALLBACK_BAD_FUNC.as_bytes(),
@@ -79,7 +78,7 @@ fn callback_selector_body(
         }
         #(#match_arms)*
         #(#module_calls)*
-        multiversx_sc::types::CallbackSelectorResult::NotProcessed(___cb_closure___)
+        multiversx_sc::types::CallbackSelectorResult::NotProcessed
     }
 }
 
@@ -123,13 +122,8 @@ pub fn module_calls(supertraits: &[Supertrait]) -> Vec<proc_macro2::TokenStream>
         .map(|supertrait| {
             let module_path = &supertrait.module_path;
             quote! {
-                match #module_path EndpointWrappers::callback_selector(self, ___cb_closure___) {
-                    multiversx_sc::types::CallbackSelectorResult::Processed => {
-                        return multiversx_sc::types::CallbackSelectorResult::Processed;
-                    },
-                    multiversx_sc::types::CallbackSelectorResult::NotProcessed(recovered_cb_closure) => {
-                        ___cb_closure___ = recovered_cb_closure;
-                    },
+                if #module_path EndpointWrappers::callback_selector(self, ___cb_closure___).is_processed() {
+                    return multiversx_sc::types::CallbackSelectorResult::Processed;
                 }
             }
         })
diff --git a/framework/scenario/tests/contract_without_macros.rs b/framework/scenario/tests/contract_without_macros.rs
index d461adea6d..29189bf898 100644
--- a/framework/scenario/tests/contract_without_macros.rs
+++ b/framework/scenario/tests/contract_without_macros.rs
@@ -83,9 +83,9 @@ mod module_1 {
         }
         fn callback_selector(
             &mut self,
-            mut ___cb_closure___: multiversx_sc::types::CallbackClosureForDeser<Self::Api>,
-        ) -> multiversx_sc::types::CallbackSelectorResult<Self::Api> {
-            multiversx_sc::types::CallbackSelectorResult::NotProcessed(___cb_closure___)
+            ___cb_closure___: &multiversx_sc::types::CallbackClosureForDeser<Self::Api>,
+        ) -> multiversx_sc::types::CallbackSelectorResult {
+            multiversx_sc::types::CallbackSelectorResult::NotProcessed
         }
     }
 
@@ -357,40 +357,25 @@ mod sample_adder {
         }
         fn callback_selector(
             &mut self,
-            mut ___cb_closure___: multiversx_sc::types::CallbackClosureForDeser<Self::Api>,
-        ) -> multiversx_sc::types::CallbackSelectorResult<Self::Api> {
+            ___cb_closure___: &multiversx_sc::types::CallbackClosureForDeser<Self::Api>,
+        ) -> multiversx_sc::types::CallbackSelectorResult {
             let ___cb_closure_matcher___ = ___cb_closure___.matcher::<32usize>();
             if ___cb_closure_matcher___.matches_empty() {
                 return multiversx_sc::types::CallbackSelectorResult::Processed;
             }
-            match super::module_1::EndpointWrappers::callback_selector(self, ___cb_closure___) {
-                multiversx_sc::types::CallbackSelectorResult::Processed => {
-                    return multiversx_sc::types::CallbackSelectorResult::Processed;
-                },
-                multiversx_sc::types::CallbackSelectorResult::NotProcessed(
-                    recovered_cb_closure,
-                ) => {
-                    ___cb_closure___ = recovered_cb_closure;
-                },
-            }
-            match super::module_1::EndpointWrappers::callback_selector(self, ___cb_closure___) {
-                multiversx_sc::types::CallbackSelectorResult::Processed => {
-                    return multiversx_sc::types::CallbackSelectorResult::Processed;
-                },
-                multiversx_sc::types::CallbackSelectorResult::NotProcessed(
-                    recovered_cb_closure,
-                ) => {
-                    ___cb_closure___ = recovered_cb_closure;
-                },
+            if super::module_1::EndpointWrappers::callback_selector(self, ___cb_closure___)
+                .is_processed()
+            {
+                return multiversx_sc::types::CallbackSelectorResult::Processed;
             }
-            multiversx_sc::types::CallbackSelectorResult::NotProcessed(___cb_closure___)
+            multiversx_sc::types::CallbackSelectorResult::NotProcessed
         }
         fn callback(&mut self) {
             if let Some(___cb_closure___) =
                 multiversx_sc::types::CallbackClosureForDeser::storage_load_and_clear::<Self::Api>()
             {
-                if let multiversx_sc::types::CallbackSelectorResult::NotProcessed(_) =
-                    self::EndpointWrappers::callback_selector(self, ___cb_closure___)
+                if !self::EndpointWrappers::callback_selector(self, &___cb_closure___)
+                    .is_processed()
                 {
                     multiversx_sc::api::ErrorApiImpl::signal_error(
                         &<Self::Api as multiversx_sc::api::ErrorApi>::error_api_impl(),

From eedd7f2c2a198248b276e0761442aacb98e17666 Mon Sep 17 00:00:00 2001
From: Andrei Marinica <andrei.marinica@multiversx.com>
Date: Wed, 11 Dec 2024 21:23:42 +0200
Subject: [PATCH 07/10] refactor: ManagedResultArgLoader removed from
 load_callback_closure_args

---
 framework/base/src/io/arg_nested_tuple.rs | 19 ++++++++-----------
 1 file changed, 8 insertions(+), 11 deletions(-)

diff --git a/framework/base/src/io/arg_nested_tuple.rs b/framework/base/src/io/arg_nested_tuple.rs
index 1a0eaace7a..aa833633d8 100644
--- a/framework/base/src/io/arg_nested_tuple.rs
+++ b/framework/base/src/io/arg_nested_tuple.rs
@@ -1,15 +1,15 @@
 use unwrap_infallible::UnwrapInfallible;
 
-use super::{EndpointDynArgLoader, EndpointSingleArgLoader, ManagedResultArgLoader};
+use super::{EndpointDynArgLoader, EndpointSingleArgLoader};
 use crate::{
     api::{
-        const_handles, use_raw_handle, EndpointArgumentApi, EndpointArgumentApiImpl, ErrorApi,
-        ErrorApiImpl, ManagedTypeApi, StaticVarApiImpl, VMApi,
+        const_handles, EndpointArgumentApi, EndpointArgumentApiImpl, ErrorApi, ErrorApiImpl,
+        ManagedTypeApi, StaticVarApiImpl, VMApi,
     },
     codec::{DecodeError, TopDecodeMulti, TopDecodeMultiInput},
     err_msg,
     io::{ArgErrorHandler, ArgId},
-    types::{ManagedArgBuffer, ManagedBuffer, ManagedType},
+    types::{ManagedArgBuffer, ManagedBuffer, ManagedType, ManagedVecRefIterator},
 };
 
 /// Argument count cannot change during execution, and it can get queried multiple times,
@@ -194,19 +194,16 @@ where
     N::next_multi_arg(loader, arg_names)
 }
 
-fn callback_closure_args_loader<AA>() -> ManagedResultArgLoader<AA>
+fn callback_closure_args_loader<AA>() -> ManagedVecRefIterator<'static, AA, ManagedBuffer<AA>>
 where
     AA: VMApi,
 {
+    let cb_closure_args_serialized = ManagedBuffer::<AA>::new();
+    AA::argument_api_impl().load_callback_closure_buffer(cb_closure_args_serialized.get_handle());
     unsafe {
-        AA::argument_api_impl()
-            .load_callback_closure_buffer(use_raw_handle(const_handles::MBUF_TEMPORARY_1));
-        let cb_closure_args_serialized =
-            ManagedBuffer::<AA>::from_raw_handle(const_handles::MBUF_TEMPORARY_1);
         let mut cb_closure_args_buffer =
             ManagedArgBuffer::<AA>::from_raw_handle(const_handles::CALLBACK_CLOSURE_ARGS_BUFFER);
         cb_closure_args_buffer.deserialize_overwrite(cb_closure_args_serialized);
-
-        ManagedResultArgLoader::new(cb_closure_args_buffer.into_vec_of_buffers())
+        ManagedVecRefIterator::new_from_handle(cb_closure_args_buffer.forget_into_handle())
     }
 }

From 806aa3f6b359577d31716f40fa6de7b413889282 Mon Sep 17 00:00:00 2001
From: Andrei Marinica <andrei.marinica@multiversx.com>
Date: Wed, 11 Dec 2024 21:23:55 +0200
Subject: [PATCH 08/10] removed ManagedResultArgLoader

---
 framework/base/src/io.rs                      |  2 -
 .../base/src/io/managed_result_arg_loader.rs  | 52 -------------------
 .../managed/wrapped/managed_vec_iter_ref.rs   |  8 ++-
 3 files changed, 6 insertions(+), 56 deletions(-)
 delete mode 100644 framework/base/src/io/managed_result_arg_loader.rs

diff --git a/framework/base/src/io.rs b/framework/base/src/io.rs
index be7f4444f6..7d71dd2e27 100644
--- a/framework/base/src/io.rs
+++ b/framework/base/src/io.rs
@@ -7,7 +7,6 @@ mod arg_nested_tuple;
 mod bytes_arg_loader;
 pub mod call_value_init;
 mod finish;
-mod managed_result_arg_loader;
 mod signal_error;
 
 pub use arg_de_input::*;
@@ -18,5 +17,4 @@ use arg_loader_single::*;
 pub use arg_nested_tuple::*;
 pub use bytes_arg_loader::*;
 pub use finish::*;
-pub use managed_result_arg_loader::*;
 pub use signal_error::*;
diff --git a/framework/base/src/io/managed_result_arg_loader.rs b/framework/base/src/io/managed_result_arg_loader.rs
deleted file mode 100644
index 77bc9967e1..0000000000
--- a/framework/base/src/io/managed_result_arg_loader.rs
+++ /dev/null
@@ -1,52 +0,0 @@
-use crate::codec::{DecodeError, DecodeErrorHandler, TopDecodeMultiInput};
-
-use crate::{
-    api::{ErrorApi, ManagedTypeApi},
-    types::{ManagedBuffer, ManagedVec},
-};
-
-pub struct ManagedResultArgLoader<A>
-where
-    A: ManagedTypeApi + ErrorApi,
-{
-    data: ManagedVec<A, ManagedBuffer<A>>,
-    data_len: usize,
-    next_index: usize,
-}
-
-impl<A> ManagedResultArgLoader<A>
-where
-    A: ManagedTypeApi + ErrorApi,
-{
-    pub fn new(data: ManagedVec<A, ManagedBuffer<A>>) -> Self {
-        let data_len = data.len();
-        ManagedResultArgLoader {
-            data,
-            data_len,
-            next_index: 0,
-        }
-    }
-}
-
-impl<A> TopDecodeMultiInput for ManagedResultArgLoader<A>
-where
-    A: ManagedTypeApi + ErrorApi,
-{
-    type ValueInput = ManagedBuffer<A>;
-
-    fn has_next(&self) -> bool {
-        self.next_index < self.data_len
-    }
-
-    fn next_value_input<H>(&mut self, h: H) -> Result<Self::ValueInput, H::HandledErr>
-    where
-        H: DecodeErrorHandler,
-    {
-        if let Some(buffer) = self.data.try_get(self.next_index) {
-            self.next_index += 1;
-            Ok((*buffer).clone())
-        } else {
-            Err(h.handle_error(DecodeError::MULTI_TOO_FEW_ARGS))
-        }
-    }
-}
diff --git a/framework/base/src/types/managed/wrapped/managed_vec_iter_ref.rs b/framework/base/src/types/managed/wrapped/managed_vec_iter_ref.rs
index ae5212c9d5..f48e3ecab1 100644
--- a/framework/base/src/types/managed/wrapped/managed_vec_iter_ref.rs
+++ b/framework/base/src/types/managed/wrapped/managed_vec_iter_ref.rs
@@ -35,15 +35,19 @@ where
     M: ManagedTypeApi,
     T: ManagedVecItem,
 {
-    pub(crate) fn new(managed_vec: &'a ManagedVec<M, T>) -> Self {
+    pub(crate) unsafe fn new_from_handle(vec_handle: M::ManagedBufferHandle) -> Self {
         unsafe {
             ManagedVecRefIterator {
-                payload_iter: ManagedVecPayloadIterator::new(managed_vec.get_handle()),
+                payload_iter: ManagedVecPayloadIterator::new(vec_handle),
                 _phantom: PhantomData,
             }
         }
     }
 
+    pub(crate) fn new(managed_vec: &'a ManagedVec<M, T>) -> Self {
+        unsafe { ManagedVecRefIterator::new_from_handle(managed_vec.get_handle()) }
+    }
+
     pub(crate) fn iter_is_empty(&self) -> bool {
         self.payload_iter.iter_is_empty()
     }

From f84bbd7e3b105d2aa607b83864cdb5ccafbd73aa Mon Sep 17 00:00:00 2001
From: BiancaIalangi <bianca.ialangi@multiversx.com>
Date: Thu, 12 Dec 2024 15:21:54 +0200
Subject: [PATCH 09/10] code report - show diff size in report

---
 framework/meta/src/cmd/code_report/compare.rs | 14 ++++++++++++--
 1 file changed, 12 insertions(+), 2 deletions(-)

diff --git a/framework/meta/src/cmd/code_report/compare.rs b/framework/meta/src/cmd/code_report/compare.rs
index 28c604962d..98f64c7738 100644
--- a/framework/meta/src/cmd/code_report/compare.rs
+++ b/framework/meta/src/cmd/code_report/compare.rs
@@ -1,10 +1,20 @@
 pub(crate) fn size_status_after_comparing(size: usize, compared_size: usize) -> String {
     match size.cmp(&compared_size) {
         std::cmp::Ordering::Greater => {
-            format!("{} :arrow_right: {} :red_circle:", compared_size, size)
+            format!(
+                "{} :arrow_right: {} :red_circle: (+{})",
+                compared_size,
+                size,
+                size - compared_size
+            )
         },
         std::cmp::Ordering::Less => {
-            format!("{} :arrow_right: {} :green_circle:", compared_size, size)
+            format!(
+                "{} :arrow_right: {} :green_circle: (-{})",
+                compared_size,
+                size,
+                compared_size - size
+            )
         },
         std::cmp::Ordering::Equal => {
             format!("{}", size)

From 96a414af84aa2f12b1e8646432ec909e518d1928 Mon Sep 17 00:00:00 2001
From: Andrei Marinica <andrei.marinica@multiversx.com>
Date: Thu, 12 Dec 2024 16:34:02 +0200
Subject: [PATCH 10/10] ContractObj wraps UniversalContractObj

---
 framework/derive/src/generate/snippets.rs     | 20 +++++++------------
 .../scenario/tests/contract_without_macros.rs | 17 ++++++----------
 2 files changed, 13 insertions(+), 24 deletions(-)

diff --git a/framework/derive/src/generate/snippets.rs b/framework/derive/src/generate/snippets.rs
index 91fc8a863f..64c590ad5f 100644
--- a/framework/derive/src/generate/snippets.rs
+++ b/framework/derive/src/generate/snippets.rs
@@ -1,11 +1,8 @@
 pub fn contract_object_def() -> proc_macro2::TokenStream {
     quote! {
-        pub struct ContractObj<A>
-        where
-            A: multiversx_sc::api::VMApi,
-        {
-            _phantom: core::marker::PhantomData<A>,
-        }
+    pub struct ContractObj<A>(multiversx_sc::contract_base::UniversalContractObj<A>)
+    where
+        A: multiversx_sc::api::VMApi;
     }
 }
 
@@ -26,9 +23,7 @@ pub fn new_contract_object_fn() -> proc_macro2::TokenStream {
         where
             A: multiversx_sc::api::VMApi,
         {
-            ContractObj {
-                _phantom: core::marker::PhantomData,
-            }
+            ContractObj::<A>(multiversx_sc::contract_base::UniversalContractObj::<A>::new())
         }
 
         pub struct ContractBuilder;
@@ -36,10 +31,9 @@ pub fn new_contract_object_fn() -> proc_macro2::TokenStream {
         impl multiversx_sc::contract_base::CallableContractBuilder for self::ContractBuilder {
             fn new_contract_obj<A: multiversx_sc::api::VMApi + Send + Sync>(
                 &self,
-            ) -> multiversx_sc::types::heap::Box<dyn multiversx_sc::contract_base::CallableContract> {
-                multiversx_sc::types::heap::Box::new(ContractObj::<A> {
-                    _phantom: core::marker::PhantomData,
-                })
+            ) -> multiversx_sc::types::heap::Box<dyn multiversx_sc::contract_base::CallableContract>
+            {
+                multiversx_sc::types::heap::Box::new(self::contract_obj::<A>())
             }
         }
     }
diff --git a/framework/scenario/tests/contract_without_macros.rs b/framework/scenario/tests/contract_without_macros.rs
index 29189bf898..d0da5fac52 100644
--- a/framework/scenario/tests/contract_without_macros.rs
+++ b/framework/scenario/tests/contract_without_macros.rs
@@ -592,12 +592,9 @@ mod sample_adder {
     /////////////////////////////////////////////////////////////////////////////////////////////////
     //////// CONTRACT OBJECT ////////////////////////////////////////////////////////////////////////
     /////////////////////////////////////////////////////////////////////////////////////////////////
-    pub struct ContractObj<A>
+    pub struct ContractObj<A>(multiversx_sc::contract_base::UniversalContractObj<A>)
     where
-        A: multiversx_sc::api::VMApi,
-    {
-        _phantom: core::marker::PhantomData<A>,
-    }
+        A: multiversx_sc::api::VMApi;
 
     /////////////////////////////////////////////////////////////////////////////////////////////////
     //////// CONTRACT OBJECT as CONTRACT BASE ///////////////////////////////////////////////////////
@@ -633,19 +630,17 @@ mod sample_adder {
     where
         A: multiversx_sc::api::VMApi,
     {
-        ContractObj {
-            _phantom: core::marker::PhantomData,
-        }
+        ContractObj::<A>(multiversx_sc::contract_base::UniversalContractObj::<A>::new())
     }
+
     pub struct ContractBuilder;
+
     impl multiversx_sc::contract_base::CallableContractBuilder for self::ContractBuilder {
         fn new_contract_obj<A: multiversx_sc::api::VMApi + Send + Sync>(
             &self,
         ) -> multiversx_sc::types::heap::Box<dyn multiversx_sc::contract_base::CallableContract>
         {
-            multiversx_sc::types::heap::Box::new(ContractObj::<A> {
-                _phantom: core::marker::PhantomData,
-            })
+            multiversx_sc::types::heap::Box::new(self::contract_obj::<A>())
         }
     }