diff --git a/.github/workflows/actions-nightly.yml b/.github/workflows/actions-nightly.yml index ecd275e033..1569c9a99c 100644 --- a/.github/workflows/actions-nightly.yml +++ b/.github/workflows/actions-nightly.yml @@ -19,7 +19,7 @@ jobs: rust-toolchain: nightly-2024-05-22 path-to-sc-meta: framework/meta enable-contracts-size-report: false - mx-scenario-go-version: v2.1.0-alpha + mx-scenario-go-version: v3.0.0 coverage-args: --ignore-filename-regex='meta/src' --ignore-filename-regex='wasm-adapter' --ignore-filename-regex='benchmarks/' --ignore-filename-regex='tests/' --output ./coverage.md secrets: token: ${{ secrets.GITHUB_TOKEN }} diff --git a/.github/workflows/actions.yml b/.github/workflows/actions.yml index a5c3eb476f..225a894772 100644 --- a/.github/workflows/actions.yml +++ b/.github/workflows/actions.yml @@ -18,7 +18,7 @@ jobs: with: rust-toolchain: 1.82 path-to-sc-meta: framework/meta - mx-scenario-go-version: v2.1.0-alpha + mx-scenario-go-version: v3.0.0 coverage-args: --ignore-filename-regex='meta/src' --ignore-filename-regex='wasm-adapter' --ignore-filename-regex='benchmarks/' --ignore-filename-regex='tests/' --output ./coverage.md secrets: token: ${{ secrets.GITHUB_TOKEN }} diff --git a/.github/workflows/template-test-current.yml b/.github/workflows/template-test-current.yml index d496bb7856..78594ed1d9 100644 --- a/.github/workflows/template-test-current.yml +++ b/.github/workflows/template-test-current.yml @@ -29,7 +29,7 @@ jobs: run: | cargo install wasm-opt cargo install --path framework/meta - sc-meta install mx-scenario-go --tag v2.0.0 + sc-meta install mx-scenario-go --tag v3.0.0 which wasm-opt which mx-scenario-go diff --git a/.github/workflows/template-test-released.yml b/.github/workflows/template-test-released.yml index 5a7ad019e3..5f68dea82d 100644 --- a/.github/workflows/template-test-released.yml +++ b/.github/workflows/template-test-released.yml @@ -29,7 +29,7 @@ jobs: run: | cargo install wasm-opt cargo install --path framework/meta - sc-meta install mx-scenario-go --tag v2.0.0 + sc-meta install mx-scenario-go --tag v3.0.0 which wasm-opt which mx-scenario-go diff --git a/Cargo.lock b/Cargo.lock index f3279b7569..3a07185582 100755 --- a/Cargo.lock +++ b/Cargo.lock @@ -262,6 +262,7 @@ dependencies = [ "clap", "multiversx-sc-snippets", "serde", + "serial_test", "tokio", "toml", ] @@ -2437,9 +2438,9 @@ dependencies = [ [[package]] name = "multiversx-chain-vm-executor" -version = "0.2.0" +version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b59072fa0624b55ae5ae3fa6bfa91515bbeb4ac440214bc4a509e2c8806d6e9f" +checksum = "51cce7ae386960fbf5e85afe40ca16d63f926f0620ed1a36b019212b28e17219" [[package]] name = "multiversx-price-aggregator-sc" @@ -3676,6 +3677,15 @@ dependencies = [ "winapi-util", ] +[[package]] +name = "scc" +version = "2.2.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "94b13f8ea6177672c49d12ed964cca44836f59621981b04a3e26b87e675181de" +dependencies = [ + "sdd", +] + [[package]] name = "scenario-tester" version = "0.0.0" @@ -3719,6 +3729,12 @@ dependencies = [ "sha2", ] +[[package]] +name = "sdd" +version = "3.0.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "478f121bb72bbf63c52c93011ea1791dca40140dfe13f8336c4c5ac952c33aa9" + [[package]] name = "second-contract" version = "0.0.0" @@ -3874,6 +3890,31 @@ dependencies = [ "serde", ] +[[package]] +name = "serial_test" +version = "3.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1b258109f244e1d6891bf1053a55d63a5cd4f8f4c30cf9a1280989f80e7a1fa9" +dependencies = [ + "futures", + "log", + "once_cell", + "parking_lot", + "scc", + "serial_test_derive", +] + +[[package]] +name = "serial_test_derive" +version = "3.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5d69265a08751de7844521fd15003ae0a888e035773ba05695c5c759a6f89eef" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.77", +] + [[package]] name = "set-repeat" version = "0.0.0" diff --git a/chain/core/src/types/flags/esdt_token_type.rs b/chain/core/src/types/flags/esdt_token_type.rs index 74db07c9a6..3668ca6fe6 100644 --- a/chain/core/src/types/flags/esdt_token_type.rs +++ b/chain/core/src/types/flags/esdt_token_type.rs @@ -13,7 +13,7 @@ const ESDT_TYPE_INVALID: &[u8] = &[]; // Note: In the current implementation, SemiFungible is never returned -#[derive(TopDecode, TopEncode, NestedDecode, NestedEncode, Clone, PartialEq, Eq, Debug)] +#[derive(TopDecode, TopEncode, NestedDecode, NestedEncode, Clone, Copy, PartialEq, Eq, Debug)] pub enum EsdtTokenType { Fungible, NonFungible, diff --git a/chain/vm/Cargo.toml b/chain/vm/Cargo.toml index 0d02932800..827d55e638 100644 --- a/chain/vm/Cargo.toml +++ b/chain/vm/Cargo.toml @@ -39,4 +39,4 @@ version = "=0.11.1" path = "../core" [dependencies.multiversx-chain-vm-executor] -version = "0.2.0" +version = "0.3.0" diff --git a/chain/vm/src/tx_execution/exec_general_tx.rs b/chain/vm/src/tx_execution/exec_general_tx.rs index 2100e3fb20..53ca60bc30 100644 --- a/chain/vm/src/tx_execution/exec_general_tx.rs +++ b/chain/vm/src/tx_execution/exec_general_tx.rs @@ -52,6 +52,18 @@ pub(crate) fn create_transfer_value_log(tx_input: &TxInput, call_type: CallType) let mut data = vec![call_type.to_log_bytes(), tx_input.func_name.to_bytes()]; data.append(&mut tx_input.args.clone()); + if tx_input.esdt_values.is_empty() + && !tx_input.callback_payments.egld_value.is_zero() + && tx_input.call_type == CallType::AsyncCallback + { + return TxLog { + address: tx_input.from.clone(), + endpoint: "transferValueOnly".into(), + topics: vec![b"".to_vec(), tx_input.to.to_vec()], + data, + }; + } + let egld_value = if tx_input.call_type == CallType::AsyncCallback { &tx_input.callback_payments.egld_value } else { diff --git a/chain/vm/src/tx_execution/system_sc/system_sc_unimplemented.rs b/chain/vm/src/tx_execution/system_sc/system_sc_unimplemented.rs index cf93be7727..a324f34900 100644 --- a/chain/vm/src/tx_execution/system_sc/system_sc_unimplemented.rs +++ b/chain/vm/src/tx_execution/system_sc/system_sc_unimplemented.rs @@ -3,8 +3,8 @@ use crate::tx_mock::{BlockchainUpdate, TxCache, TxInput, TxResult}; /// Every unimplemented fn will be implemented and moved to its corresponding file. +/// /// This file will be deleted. - pub fn register_meta_esdt(tx_input: TxInput, tx_cache: TxCache) -> (TxResult, BlockchainUpdate) { unimplemented!() } diff --git a/chain/vm/src/vm_hooks/vh_dispatcher.rs b/chain/vm/src/vm_hooks/vh_dispatcher.rs index 0dbfc54051..1af9bfbb6a 100644 --- a/chain/vm/src/vm_hooks/vh_dispatcher.rs +++ b/chain/vm/src/vm_hooks/vh_dispatcher.rs @@ -1859,4 +1859,53 @@ impl VMHooks for VMHooksDispatcher { ) -> i32 { panic!("Unavailable: elliptic_curve_get_values") } + + fn is_reserved_function_name(&self, name_handle: i32) -> i32 { + panic!("Unavailable: is_reserved_function_name") + } + + fn managed_get_original_caller_addr(&self, destination_handle: i32) { + panic!("Unavailable: managed_get_original_caller_addr") + } + + fn managed_get_relayer_addr(&self, destination_handle: i32) { + panic!("Unavailable: managed_get_relayer_addr") + } + + fn managed_multi_transfer_esdt_nft_execute_by_user( + &self, + user_handle: i32, + dst_handle: i32, + token_transfers_handle: i32, + gas_limit: i64, + function_handle: i32, + arguments_handle: i32, + ) -> i32 { + panic!("Unavailable: managed_multi_transfer_esdt_nft_execute_by_user") + } + + fn managed_verify_secp256r1( + &self, + key_handle: i32, + message_handle: i32, + sig_handle: i32, + ) -> i32 { + panic!("Unavailable: managed_verify_secp256r1") + } + fn managed_verify_blssignature_share( + &self, + key_handle: i32, + message_handle: i32, + sig_handle: i32, + ) -> i32 { + panic!("Unavailable: managed_verify_blssignature_share") + } + fn managed_verify_blsaggregated_signature( + &self, + key_handle: i32, + message_handle: i32, + sig_handle: i32, + ) -> i32 { + panic!("Unavailable: managed_verify_blsaggregated_signature") + } } 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
) { .to(PRICE_AGGREGATOR_ADDRESS) .egld(STAKE_AMOUNT) .whitebox(multiversx_price_aggregator_sc::contract_obj, |sc| { - sc.call_stake(); + sc.stake(); }); } diff --git a/contracts/core/wegld-swap/src/wegld.rs b/contracts/core/wegld-swap/src/wegld.rs index 23a4493494..1c9cf11a2a 100644 --- a/contracts/core/wegld-swap/src/wegld.rs +++ b/contracts/core/wegld-swap/src/wegld.rs @@ -39,10 +39,10 @@ pub trait EgldEsdtSwap: multiversx_sc_modules::pause::PauseModule { let (payment_token, payment_amount) = self.call_value().single_fungible_esdt(); let wrapped_egld_token_id = self.wrapped_egld_token_id().get(); - require!(payment_token == wrapped_egld_token_id, "Wrong esdt token"); - require!(payment_amount > 0u32, "Must pay more than 0 tokens!"); + require!(*payment_token == wrapped_egld_token_id, "Wrong esdt token"); + require!(*payment_amount > 0u32, "Must pay more than 0 tokens!"); require!( - payment_amount <= self.get_locked_egld_balance(), + *payment_amount <= self.get_locked_egld_balance(), "Contract does not have enough funds" ); @@ -51,7 +51,7 @@ pub trait EgldEsdtSwap: multiversx_sc_modules::pause::PauseModule { // 1 wrapped eGLD = 1 eGLD, so we pay back the same amount let caller = self.blockchain().get_caller(); - self.tx().to(&caller).egld(&payment_amount).transfer(); + self.tx().to(&caller).egld(&*payment_amount).transfer(); } #[view(getLockedEgldBalance)] diff --git a/contracts/examples/adder/interactor/Cargo.toml b/contracts/examples/adder/interactor/Cargo.toml index 06507f3b74..97fbe441ed 100644 --- a/contracts/examples/adder/interactor/Cargo.toml +++ b/contracts/examples/adder/interactor/Cargo.toml @@ -24,6 +24,7 @@ clap = { version = "4.4.7", features = ["derive"] } serde = { version = "1.0", features = ["derive"] } toml = "0.8.6" tokio = { version = "1.24" } +serial_test = { version = "3.2.0" } [features] chain-simulator-tests = [] diff --git a/contracts/examples/adder/interactor/set_state.json b/contracts/examples/adder/interactor/set_state.json new file mode 100644 index 0000000000..a5115b7781 --- /dev/null +++ b/contracts/examples/adder/interactor/set_state.json @@ -0,0 +1,82 @@ +[ + { + "address": "erd1uv40ahysflse896x4ktnh6ecx43u7cmy9wnxnvcyp7deg299a4sq6vaywa", + "nonce": 5947, + "balance": "491982310359999986", + "keys": { + "454c524f4e44657364745453542d363437383930": "1209004563918244f40000", + "454c524f4e446e6f6e636550544d2d353336666162": "01", + "454c524f4e446573647450544d2d35333666616201": "08021202000122ef0108011212546573742d5061696e742d486172766573741a20e32afedc904fe1939746ad973beb383563cf63642ba669b3040f9b9428a5ed6020c4132a2e516d57564239575362674b52655a64615a434344766b454b70705a6b4d696d397563736e7857565041414c6a4374324368747470733a2f2f697066732e696f2f697066732f516d57564239575362674b52655a64615a434344766b454b70705a6b4d696d397563736e7857565041414c6a43743a3d746167733a3b6d657461646174613a516d52635039346b5872357a5a6a52477669376d4a36756e374c7078556859565234523452706963787a67596b74", + "454c524f4e44726f6c656573647450544d2d353336666162": "0a1145534454526f6c654e46544372656174650a0f45534454526f6c654e46544275726e", + "454c524f4e44657364745453542d633565303835": "1209004563918244f40000", + "454c524f4e44657364745453542d346230653865": "1209004563918244f40000", + "454c524f4e44657364744c5453542d346638343965": "1209000de0b6b3a763fc19", + "454c524f4e44657364745453542d393864633566": "1209004563918244f40000", + "454c524f4e44657364745453542d396230323030": "1209004563918244f40000", + "454c524f4e44657364745453542d386564363538": "1209004563918244f40000", + "454c524f4e44657364745453542d643862306438": "12020064", + "454c524f4e44657364745453542d363835303064": "1209004563918244f40000", + "454c524f4e44657364745453542d323833633361": "12020064", + "454c524f4e44657364745453542d333331386638": "1209004563918244f40000", + "454c524f4e44657364745453542d303637373232": "1209004563918244f40000", + "454c524f4e44657364745745474c442d613238633539": "120900389351ce08f09e12", + "454c524f4e44657364745453542d343138613232": "1209004563918244f40000", + "454c524f4e44657364745453542d656338383735": "12020064", + "454c524f4e44657364745453542d333639646531": "1209004563918244f40000", + "454c524f4e44657364745453542d373639313337": "1209004563918244f40000", + "454c524f4e44657364745453542d363434633935": "12020064", + "454c524f4e44657364745453542d623830663863": "1209004563918244f40000", + "454c524f4e4465736474475245454e2d306531363163": "120b00152d02c7e14af67fffdc", + "454c524f4e4465736474424358535542542d33393264366172": "080112020001", + "454c524f4e44657364745453542d343562383235": "12020064", + "454c524f4e44657364745453542d613562663131": "12020064", + "454c524f4e44657364745453542d623130616461": "1209004563918244f40000", + "454c524f4e44657364745453542d633933336139": "1209004563918244f40000", + "454c524f4e44657364744c5453542d376266336431": "1209000de0b6b3a763fc19", + "454c524f4e44657364745453542d336339363762": "12020064", + "454c524f4e44657364745453542d623136363735": "1209004563918244f40000", + "454c524f4e44657364745453542d303362373664": "12020064", + "454c524f4e44657364745453542d353538616434": "12020064", + "454c524f4e44657364745453542d353966316165": "1209004563918244f40000", + "454c524f4e44657364745453542d306632306637": "12020064", + "454c524f4e446573647455544b2d313464353764": "120b0001e6ce88d5ebbfd00000", + "454c524f4e44657364745453542d633636666535": "1209004563918244f40000", + "454c524f4e44657364745453542d346634303238": "12020064", + "454c524f4e44657364745453542d643964336136": "1209004563918244f40000", + "454c524f4e44657364745453542d343265356138": "1209004563918244f40000", + "454c524f4e44657364745453542d393836646663": "12020064" + }, + "code": "", + "code_hash": "", + "root_hash": "2zSeJjLqgozEQmmgDU8L0/GidcKzJOlJgwoaTUqvDFg=", + "code_metadata": "", + "owner_address": "", + "developer_reward": "0" + }, + { + "address": "erd13x29rvmp4qlgn4emgztd8jgvyzdj0p6vn37tqxas3v9mfhq4dy7shalqrx", + "nonce": 1417, + "balance": "1753855617144056", + "keys": { + "454c524f4e4465736474424358535542542d3339326436616e": "080112020001", + "454c524f4e446573647442534b2d343736343730": "120b00021e19e0c9bab23fff7b", + "454c524f4e446573647445564e544e4f544946592d393634383835": "120b00152d02c7e14af6800000", + "454c524f4e4465736474494e5445524e532d63393332356601": "0801120b0013097d1fb962e12fff47", + "454c524f4e44657364744e455453432d623635306261": "120b00d137965aa7a731800000", + "454c524f4e44657364745745474c442d613238633539": "120800010593b233281b", + "454c524f4e446e6f6e6365494e5445524e532d633933323566": "01", + "454c524f4e446e6f6e63654d4554414e46542d643062623339": "01", + "454c524f4e44726f6c6565736474494e5445524e532d633933323566": "0a1145534454526f6c654e46544372656174650a1645534454526f6c654e46544164645175616e74697479", + "454c524f4e44657364744e4943552d393730323932": "120b00d3c21bcecceda1000000", + "454c524f4e44726f6c65657364744d4554414e46542d643062623339": "0a1145534454526f6c654e4654437265617465", + "454c524f4e4465736474424358535542542d3339326436616c": "080112020001", + "454c524f4e44657364744e45543253432d306438663962": "120f0004ee2d6d3f3d6bcc25c64dc00000" + }, + "code": "", + "code_hash": "", + "root_hash": "AJ2jyOcPXgZAl0kHAlbWZIlG3F1VDtcoLAHR6eqehBA=", + "code_metadata": "", + "owner_address": "", + "developer_reward": "0" + } +] \ No newline at end of file diff --git a/contracts/examples/adder/interactor/src/basic_interactor.rs b/contracts/examples/adder/interactor/src/basic_interactor.rs index 63d71de11a..fc08f50357 100644 --- a/contracts/examples/adder/interactor/src/basic_interactor.rs +++ b/contracts/examples/adder/interactor/src/basic_interactor.rs @@ -57,7 +57,7 @@ impl AdderInteract { let adder_owner_address = interactor.register_wallet(test_wallets::heidi()).await; let wallet_address = interactor.register_wallet(test_wallets::ivan()).await; - interactor.generate_blocks_until_epoch(1).await.unwrap(); + interactor.generate_blocks(30u64).await.unwrap(); AdderInteract { interactor, diff --git a/contracts/examples/adder/interactor/tests/basic_interactor_cs_test.rs b/contracts/examples/adder/interactor/tests/basic_interactor_cs_test.rs index 1f07ee4c87..b4e9747794 100644 --- a/contracts/examples/adder/interactor/tests/basic_interactor_cs_test.rs +++ b/contracts/examples/adder/interactor/tests/basic_interactor_cs_test.rs @@ -1,6 +1,9 @@ use basic_interactor::{AdderInteract, Config}; +use multiversx_sc_snippets::{imports::Bech32Address, sdk::gateway::SetStateAccount, test_wallets}; +use serial_test::serial; #[tokio::test] +#[serial] #[cfg_attr(not(feature = "chain-simulator-tests"), ignore)] async fn simulator_upgrade_test() { let mut basic_interact = AdderInteract::new(Config::chain_simulator_config()).await; @@ -33,3 +36,70 @@ async fn simulator_upgrade_test() { let sum = basic_interact.get_sum().await; assert_eq!(sum, 7u32.into()); } + +#[tokio::test] +#[serial] +#[cfg_attr(not(feature = "chain-simulator-tests"), ignore)] +async fn set_state_cs_test() { + let account_address = test_wallets::mike(); + + let real_chain_interact = AdderInteract::new(Config::load_config()).await; + let simulator_interact = AdderInteract::new(Config::chain_simulator_config()).await; + + let account = real_chain_interact + .interactor + .get_account(&account_address.to_address()) + .await; + let keys = real_chain_interact + .interactor + .get_account_storage(&account_address.to_address()) + .await; + + let set_state_account = SetStateAccount::from(account).with_keys(keys); + let vec_state = vec![set_state_account]; + + let set_state_response = simulator_interact.interactor.set_state(vec_state).await; + + simulator_interact + .interactor + .generate_blocks(2u64) + .await + .unwrap(); + + assert!(set_state_response.is_ok()); +} + +#[tokio::test] +#[serial] +#[cfg_attr(not(feature = "chain-simulator-tests"), ignore)] +async fn set_state_from_file_cs_test() { + let account_address = test_wallets::mike(); + let account_address_2 = test_wallets::ivan(); + + let mut real_chain_interact = AdderInteract::new(Config::load_config()).await; + let simulator_interact = AdderInteract::new(Config::chain_simulator_config()).await; + + // now we should have current mike account in the set state file + real_chain_interact + .interactor + .retrieve_account(&Bech32Address::from(&account_address.to_address())) + .await; + + real_chain_interact + .interactor + .retrieve_account(&Bech32Address::from(&account_address_2.to_address())) + .await; + + let set_state_response = simulator_interact + .interactor + .set_state_for_saved_accounts() + .await; + + simulator_interact + .interactor + .generate_blocks(2u64) + .await + .unwrap(); + + assert!(set_state_response.is_ok()); +} diff --git a/contracts/examples/bonding-curve-contract/src/bonding_curve_contract.rs b/contracts/examples/bonding-curve-contract/src/bonding_curve_contract.rs index 6ab29068d3..490eb4bb42 100644 --- a/contracts/examples/bonding-curve-contract/src/bonding_curve_contract.rs +++ b/contracts/examples/bonding-curve-contract/src/bonding_curve_contract.rs @@ -20,13 +20,13 @@ pub trait Contract: #[init] fn init(&self) {} - #[payable("*")] + #[payable] #[endpoint(sellToken)] fn sell_token_endpoint(&self) { self.sell_token::>(); } - #[payable("*")] + #[payable] #[endpoint(buyToken)] fn buy_token_endpoint( &self, @@ -42,7 +42,7 @@ pub trait Contract: } #[endpoint(deposit)] - #[payable("*")] + #[payable] fn deposit_endpoint(&self, payment_token: OptionalValue) { self.deposit::>(payment_token) } diff --git a/contracts/examples/crowdfunding-esdt/src/crowdfunding_esdt.rs b/contracts/examples/crowdfunding-esdt/src/crowdfunding_esdt.rs index d47e256f08..1c7e3acebd 100644 --- a/contracts/examples/crowdfunding-esdt/src/crowdfunding_esdt.rs +++ b/contracts/examples/crowdfunding-esdt/src/crowdfunding_esdt.rs @@ -29,7 +29,7 @@ pub trait Crowdfunding { } #[endpoint] - #[payable("*")] + #[payable] fn fund(&self) { let (token, _, payment) = self.call_value().egld_or_single_esdt().into_tuple(); diff --git a/contracts/examples/crypto-kitties/common/random/src/lib.rs b/contracts/examples/crypto-kitties/common/random/src/lib.rs index 46ddd076d6..1cfb5e3fa2 100644 --- a/contracts/examples/crypto-kitties/common/random/src/lib.rs +++ b/contracts/examples/crypto-kitties/common/random/src/lib.rs @@ -24,6 +24,7 @@ pub trait Randomizeable { impl Random { /// block random seed + salt creates a stronger randomness source + #[allow(static_mut_refs)] pub fn new( seed: ManagedByteArray, salt: ManagedByteArray, diff --git a/contracts/examples/digital-cash/src/pay_fee_and_fund.rs b/contracts/examples/digital-cash/src/pay_fee_and_fund.rs index 45e913c51d..3815ea38cc 100644 --- a/contracts/examples/digital-cash/src/pay_fee_and_fund.rs +++ b/contracts/examples/digital-cash/src/pay_fee_and_fund.rs @@ -5,10 +5,10 @@ use crate::{constants::*, helpers, storage}; #[multiversx_sc::module] pub trait PayFeeAndFund: storage::StorageModule + helpers::HelpersModule { #[endpoint(payFeeAndFundESDT)] - #[payable("*")] + #[payable] fn pay_fee_and_fund_esdt(&self, address: ManagedAddress, valability: u64) { - let mut payments = self.call_value().all_esdt_transfers().clone_value(); - let fee = EgldOrEsdtTokenPayment::from(payments.get(0)); + let mut payments = self.call_value().all_esdt_transfers().clone(); + let fee = EgldOrEsdtTokenPayment::from(payments.get(0).clone()); let caller_address = self.blockchain().get_caller(); self.update_fees(caller_address, &address, fee); @@ -32,7 +32,7 @@ pub trait PayFeeAndFund: storage::StorageModule + helpers::HelpersModule { } #[endpoint] - #[payable("*")] + #[payable] fn fund(&self, address: ManagedAddress, valability: u64) { require!(!self.deposit(&address).is_empty(), FEES_NOT_COVERED_ERR_MSG); let deposit_mapper = self.deposit(&address).get(); diff --git a/contracts/examples/digital-cash/src/signature_operations.rs b/contracts/examples/digital-cash/src/signature_operations.rs index 9c68951f05..2c31701a00 100644 --- a/contracts/examples/digital-cash/src/signature_operations.rs +++ b/contracts/examples/digital-cash/src/signature_operations.rs @@ -92,7 +92,7 @@ pub trait SignatureOperationsModule: storage::StorageModule + helpers::HelpersMo } #[endpoint] - #[payable("*")] + #[payable] fn forward( &self, address: ManagedAddress, diff --git a/contracts/examples/esdt-transfer-with-fee/src/esdt_transfer_with_fee.rs b/contracts/examples/esdt-transfer-with-fee/src/esdt_transfer_with_fee.rs index de883ef83a..b885ec371f 100644 --- a/contracts/examples/esdt-transfer-with-fee/src/esdt_transfer_with_fee.rs +++ b/contracts/examples/esdt-transfer-with-fee/src/esdt_transfer_with_fee.rs @@ -43,7 +43,7 @@ pub trait EsdtTransferWithFee { self.tx().to(ToCaller).payment(fees).transfer(); } - #[payable("*")] + #[payable] #[endpoint] fn transfer(&self, address: ManagedAddress) { require!( @@ -71,13 +71,13 @@ pub trait EsdtTransferWithFee { "Mismatching payment for covering fees" ); let _ = self.get_payment_after_fees(fee_type, &next_payment); - new_payments.push(payment); + new_payments.push(payment.clone()); }, Fee::Percentage(_) => { new_payments.push(self.get_payment_after_fees(fee_type, &payment)); }, Fee::Unset => { - new_payments.push(payment); + new_payments.push(payment.clone()); }, } } diff --git a/contracts/examples/fractional-nfts/src/fractional_nfts.rs b/contracts/examples/fractional-nfts/src/fractional_nfts.rs index 16f1c87aed..fea51e2431 100644 --- a/contracts/examples/fractional-nfts/src/fractional_nfts.rs +++ b/contracts/examples/fractional-nfts/src/fractional_nfts.rs @@ -47,7 +47,7 @@ pub trait FractionalNfts: default_issue_callbacks::DefaultIssueCallbacksModule { .async_call_and_exit(); } - #[payable("*")] + #[payable] #[endpoint(fractionalizeNFT)] fn fractionalize_nft( &self, @@ -74,7 +74,7 @@ pub trait FractionalNfts: default_issue_callbacks::DefaultIssueCallbacksModule { let fractional_token = fractional_token_mapper.get_token_id_ref(); let hash = ManagedBuffer::new(); let fractional_info = - FractionalUriInfo::new(original_payment, initial_fractional_amount.clone()); + FractionalUriInfo::new(original_payment.clone(), initial_fractional_amount.clone()); let uris = fractional_info.to_uris(); let fractional_nonce = self.send().esdt_nft_create( @@ -97,7 +97,7 @@ pub trait FractionalNfts: default_issue_callbacks::DefaultIssueCallbacksModule { .transfer(); } - #[payable("*")] + #[payable] #[endpoint(unFractionalizeNFT)] fn unfractionalize_nft(&self) { let fractional_payment = self.call_value().single_esdt(); diff --git a/contracts/examples/lottery-esdt/src/lottery.rs b/contracts/examples/lottery-esdt/src/lottery.rs index 3c5d9040b1..026710d5c7 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()); } } @@ -166,7 +166,7 @@ pub trait Lottery { } #[endpoint] - #[payable("*")] + #[payable] fn buy_ticket(&self, lottery_name: ManagedBuffer) { let (token_identifier, payment) = self.call_value().egld_or_single_fungible_esdt(); diff --git a/contracts/examples/multisig/src/multisig.rs b/contracts/examples/multisig/src/multisig.rs index d1e177df02..4c32bb8f0a 100644 --- a/contracts/examples/multisig/src/multisig.rs +++ b/contracts/examples/multisig/src/multisig.rs @@ -49,7 +49,7 @@ pub trait Multisig: } /// Allows the contract to receive funds even if it is marked as unpayable in the protocol. - #[payable("*")] + #[payable] #[endpoint] fn deposit(&self) {} 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/nft-minter/src/nft_module.rs b/contracts/examples/nft-minter/src/nft_module.rs index ab4fd22504..6629c22d11 100644 --- a/contracts/examples/nft-minter/src/nft_module.rs +++ b/contracts/examples/nft-minter/src/nft_module.rs @@ -59,7 +59,7 @@ pub trait NftModule { // endpoints - #[payable("*")] + #[payable] #[endpoint(buyNft)] fn buy_nft(&self, nft_nonce: u64) { let payment = self.call_value().egld_or_single_esdt(); diff --git a/contracts/examples/nft-subscription/src/lib.rs b/contracts/examples/nft-subscription/src/lib.rs index 7b0b63096e..beca5ac5bf 100644 --- a/contracts/examples/nft-subscription/src/lib.rs +++ b/contracts/examples/nft-subscription/src/lib.rs @@ -46,37 +46,57 @@ pub trait NftSubscription: .transfer(); } - #[payable("*")] + #[payable] #[endpoint] fn update_attributes(&self, attributes: ManagedBuffer) { - let (id, nonce, _) = self.call_value().single_esdt().into_tuple(); - self.update_subscription_attributes::(&id, nonce, attributes); + let payment = self.call_value().single_esdt(); + self.update_subscription_attributes::( + &payment.token_identifier, + payment.token_nonce, + attributes, + ); self.tx() .to(ToCaller) - .single_esdt(&id, nonce, &BigUint::from(1u8)) + .single_esdt( + &payment.token_identifier, + payment.token_nonce, + &BigUint::from(1u8), + ) .transfer(); } - #[payable("*")] + #[payable] #[endpoint] fn renew(&self, duration: u64) { - let (id, nonce, _) = self.call_value().single_esdt().into_tuple(); - self.renew_subscription::(&id, nonce, duration); + let payment = self.call_value().single_esdt(); + self.renew_subscription::( + &payment.token_identifier, + payment.token_nonce, + duration, + ); self.tx() .to(ToCaller) - .single_esdt(&id, nonce, &BigUint::from(1u8)) + .single_esdt( + &payment.token_identifier, + payment.token_nonce, + &BigUint::from(1u8), + ) .transfer(); } - #[payable("*")] + #[payable] #[endpoint] fn cancel(&self) { - let (id, nonce, _) = self.call_value().single_esdt().into_tuple(); - self.cancel_subscription::(&id, nonce); + let payment = self.call_value().single_esdt(); + self.cancel_subscription::(&payment.token_identifier, payment.token_nonce); self.tx() .to(ToCaller) - .single_esdt(&id, nonce, &BigUint::from(1u8)) + .single_esdt( + &payment.token_identifier, + payment.token_nonce, + &BigUint::from(1u8), + ) .transfer(); } diff --git a/contracts/examples/order-book/pair/src/common.rs b/contracts/examples/order-book/pair/src/common.rs index 7728e4c364..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, + 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..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); } @@ -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/lib.rs b/contracts/examples/order-book/pair/src/lib.rs index 69e3a9f8c5..d1e8a2aa21 100644 --- a/contracts/examples/order-book/pair/src/lib.rs +++ b/contracts/examples/order-book/pair/src/lib.rs @@ -24,7 +24,7 @@ pub trait Pair: self.second_token_id().set_if_empty(&second_token_id); } - #[payable("*")] + #[payable] #[endpoint(createBuyOrder)] fn create_buy_order_endpoint(&self, params: OrderInputParams) { self.require_global_op_not_ongoing(); @@ -34,7 +34,7 @@ pub trait Pair: self.create_order(payment, params, common::OrderType::Buy); } - #[payable("*")] + #[payable] #[endpoint(createSellOrder)] fn create_sell_order_endpoint(&self, params: OrderInputParams) { self.require_global_op_not_ongoing(); 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/order-book/pair/src/validation.rs b/contracts/examples/order-book/pair/src/validation.rs index 488edbdb24..306f299014 100644 --- a/contracts/examples/order-book/pair/src/validation.rs +++ b/contracts/examples/order-book/pair/src/validation.rs @@ -72,22 +72,28 @@ pub trait ValidationModule: common::CommonModule { let (token_id, amount) = self.call_value().single_fungible_esdt(); let second_token_id = self.second_token_id().get(); require!( - token_id == second_token_id, + *token_id == second_token_id, "Token in and second token id should be the same" ); - Payment { token_id, amount } + Payment { + token_id: token_id.clone(), + amount: amount.clone(), + } } fn require_valid_sell_payment(&self) -> Payment { let (token_id, amount) = self.call_value().single_fungible_esdt(); let first_token_id = self.first_token_id().get(); require!( - token_id == first_token_id, + *token_id == first_token_id, "Token in and first token id should be the same" ); - Payment { token_id, amount } + Payment { + token_id: token_id.clone(), + amount: amount.clone(), + } } fn require_valid_match_input_order_ids(&self, order_ids: &ManagedVec) { diff --git a/contracts/examples/rewards-distribution/src/rewards_distribution.rs b/contracts/examples/rewards-distribution/src/rewards_distribution.rs index 7300fcaf88..48ba549a9e 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, @@ -57,7 +57,7 @@ pub trait RewardsDistribution: self.brackets().set(brackets); } - #[payable("*")] + #[payable] #[endpoint(depositRoyalties)] fn deposit_royalties(&self) { let payment = self.call_value().egld_or_single_esdt(); @@ -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(); } } @@ -247,7 +247,7 @@ pub trait RewardsDistribution: ); } - #[payable("*")] + #[payable] #[endpoint(claimRewards)] fn claim_rewards( &self, 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/examples/seed-nft-minter/src/nft_module.rs b/contracts/examples/seed-nft-minter/src/nft_module.rs index 3580ecedb5..8c271e5686 100644 --- a/contracts/examples/seed-nft-minter/src/nft_module.rs +++ b/contracts/examples/seed-nft-minter/src/nft_module.rs @@ -38,7 +38,7 @@ pub trait NftModule: // endpoints - #[payable("*")] + #[payable] #[endpoint(buyNft)] fn buy_nft(&self, nft_nonce: u64) { let payment = self.call_value().egld_or_single_esdt(); 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..98734c0fb0 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); } @@ -102,7 +102,7 @@ pub trait SeedNftMinter: } else { esdt_payments .try_get(0) - .map(|esdt_payment| esdt_payment.amount) + .map(|esdt_payment| esdt_payment.amount.clone()) .unwrap_or_default() }; total_amount += amount; diff --git a/contracts/feature-tests/alloc-features/scenarios/alloc_mem_fail.scen.json b/contracts/feature-tests/alloc-features/scenarios/alloc_mem_fail.scen.json index 5185e53638..c8f86f7292 100644 --- a/contracts/feature-tests/alloc-features/scenarios/alloc_mem_fail.scen.json +++ b/contracts/feature-tests/alloc-features/scenarios/alloc_mem_fail.scen.json @@ -7,7 +7,7 @@ "sc:alloc-mem-fail": { "nonce": "0", "balance": "0", - "code": "file:../output/alloc-mem-fail.wasm" + "code": "mxsc:../output/alloc-mem-fail.mxsc.json" }, "address:an_account": { "nonce": "0", diff --git a/contracts/feature-tests/alloc-features/scenarios/alloc_mem_leaking.scen.json b/contracts/feature-tests/alloc-features/scenarios/alloc_mem_leaking.scen.json index 0cae3b7303..95f33ac733 100644 --- a/contracts/feature-tests/alloc-features/scenarios/alloc_mem_leaking.scen.json +++ b/contracts/feature-tests/alloc-features/scenarios/alloc_mem_leaking.scen.json @@ -7,7 +7,7 @@ "sc:alloc-mem-leaking": { "nonce": "0", "balance": "0", - "code": "file:../output/alloc-mem-leaking.wasm" + "code": "mxsc:../output/alloc-mem-leaking.mxsc.json" }, "address:an_account": { "nonce": "0", diff --git a/contracts/feature-tests/basic-features/scenarios/crypto_verify_bls.scen.json b/contracts/feature-tests/basic-features/scenarios/crypto_verify_bls.scen.json index fc67a3745b..99d683d28d 100644 --- a/contracts/feature-tests/basic-features/scenarios/crypto_verify_bls.scen.json +++ b/contracts/feature-tests/basic-features/scenarios/crypto_verify_bls.scen.json @@ -58,7 +58,7 @@ "expect": { "out": [], "status": "10", - "message": "str:err blsSignatureDeserialize 0032a2ddf341c08d1eb7232f05dc34e4454155e676b58c40fddf9a036562ac2c01533d2d557cb49d73aa9d7a89744696", + "message": "str:signature is invalid", "logs": "*", "gas": "*", "refund": "*" diff --git a/contracts/feature-tests/basic-features/scenarios/crypto_verify_bls_aggregated_signature.scen.json b/contracts/feature-tests/basic-features/scenarios/crypto_verify_bls_aggregated_signature.scen.json index 546c0d4c9f..490fb1de8b 100644 --- a/contracts/feature-tests/basic-features/scenarios/crypto_verify_bls_aggregated_signature.scen.json +++ b/contracts/feature-tests/basic-features/scenarios/crypto_verify_bls_aggregated_signature.scen.json @@ -70,7 +70,7 @@ "expect": { "out": [], "status": "10", - "message": "str:err blsSignatureDeserialize 0012858363e8caa5b398d3febdd7bc01bc2fae1fef8f486ff4d84a5f3342f2d38085904eb10b73c0879a45d23585ce8f", + "message": "str:signature is invalid", "logs": "*", "gas": "*", "refund": "*" diff --git a/contracts/feature-tests/basic-features/scenarios/crypto_verify_bls_share.scen.json b/contracts/feature-tests/basic-features/scenarios/crypto_verify_bls_share.scen.json index fa7c21611b..2fe8473f52 100644 --- a/contracts/feature-tests/basic-features/scenarios/crypto_verify_bls_share.scen.json +++ b/contracts/feature-tests/basic-features/scenarios/crypto_verify_bls_share.scen.json @@ -58,7 +58,7 @@ "expect": { "out": [], "status": "10", - "message": "str:err blsSignatureDeserialize ff725db195e37aa237cdbbda76270d4a229b6e7a3651104dc58c4349c0388e8546976fe54a04240530b99064e434c90f", + "message": "str:signature is invalid", "logs": "*", "gas": "*", "refund": "*" diff --git a/contracts/feature-tests/basic-features/scenarios/crypto_verify_secp256r1.scen.json b/contracts/feature-tests/basic-features/scenarios/crypto_verify_secp256r1.scen.json index 1c35b46271..5d22d63d9c 100644 --- a/contracts/feature-tests/basic-features/scenarios/crypto_verify_secp256r1.scen.json +++ b/contracts/feature-tests/basic-features/scenarios/crypto_verify_secp256r1.scen.json @@ -57,7 +57,7 @@ "expect": { "out": [], "status": "10", - "message": "str:signature verification failed", + "message": "str:signature is invalid", "logs": "*", "gas": "*", "refund": "*" 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/contracts/feature-tests/basic-features/src/storage_direct_load.rs b/contracts/feature-tests/basic-features/src/storage_direct_load.rs index efdd51a20f..7d19f83eb5 100644 --- a/contracts/feature-tests/basic-features/src/storage_direct_load.rs +++ b/contracts/feature-tests/basic-features/src/storage_direct_load.rs @@ -1,7 +1,5 @@ multiversx_sc::imports!(); -use multiversx_sc::api::{use_raw_handle, HandleTypeInfo}; - use crate::types::*; /// Storage tests: direct load. @@ -78,16 +76,15 @@ pub trait StorageLoadFeatures { #[endpoint] fn load_from_address_raw(&self, address: ManagedAddress, key: ManagedBuffer) -> ManagedBuffer { // TODO: maybe wrap this kind of functionality in a StorageRawWrapper - use multiversx_sc::api::{ - StaticVarApi, StaticVarApiImpl, StorageReadApi, StorageReadApiImpl, - }; - let value_handle: <::Api as HandleTypeInfo>::ManagedBufferHandle = - use_raw_handle(Self::Api::static_var_api_impl().next_handle()); - Self::Api::storage_read_api_impl().storage_load_from_address( - address.get_handle(), - key.get_handle(), - value_handle.clone(), - ); - ManagedBuffer::from_handle(value_handle) + use multiversx_sc::api::{StorageReadApi, StorageReadApiImpl}; + unsafe { + let value = ManagedBuffer::new_uninit(); + Self::Api::storage_read_api_impl().storage_load_from_address( + address.get_handle(), + key.get_handle(), + value.get_handle(), + ); + value + } } } diff --git a/contracts/feature-tests/basic-features/src/storage_mapper_fungible_token.rs b/contracts/feature-tests/basic-features/src/storage_mapper_fungible_token.rs index 6eccdd3f83..feeecb2b33 100644 --- a/contracts/feature-tests/basic-features/src/storage_mapper_fungible_token.rs +++ b/contracts/feature-tests/basic-features/src/storage_mapper_fungible_token.rs @@ -61,8 +61,9 @@ pub trait FungibleTokenMapperFeatures: fn custom_issue_non_zero_supply_cb(&self, #[call_result] result: ManagedAsyncCallResult<()>) { match result { ManagedAsyncCallResult::Ok(()) => { - let token_identifier = self.call_value().single_esdt().token_identifier; - self.fungible_token_mapper().set_token_id(token_identifier); + let token_identifier = &self.call_value().single_esdt().token_identifier; + self.fungible_token_mapper() + .set_token_id(token_identifier.clone()); }, ManagedAsyncCallResult::Err(_) => { self.fungible_token_mapper().clear(); @@ -128,9 +129,9 @@ pub trait FungibleTokenMapperFeatures: #[payable("*")] #[endpoint] fn require_same_token_fungible(&self) { - let payment_token = self.call_value().single_esdt().token_identifier; + let payment_token = &self.call_value().single_esdt().token_identifier; self.fungible_token_mapper() - .require_same_token(&payment_token); + .require_same_token(payment_token); } #[payable("*")] 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..f4d09b555e 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 @@ -25,7 +25,7 @@ pub trait FirstContract { let expected_token_identifier = self.get_contract_esdt_token_identifier(); require!( - actual_token_identifier == expected_token_identifier, + *actual_token_identifier == expected_token_identifier, "Wrong esdt token" ); @@ -45,13 +45,13 @@ pub trait FirstContract { let expected_token_identifier = self.get_contract_esdt_token_identifier(); require!( - actual_token_identifier == expected_token_identifier, + *actual_token_identifier == expected_token_identifier, "Wrong esdt token" ); self.call_esdt_second_contract( &expected_token_identifier, - &(esdt_value / 2u32), + &(esdt_value.clone() / 2u32), &self.get_second_contract_address(), &ManagedBuffer::from(SECOND_CONTRACT_ACCEPT_ESDT_PAYMENT), &ManagedVec::new(), @@ -65,7 +65,7 @@ pub trait FirstContract { let expected_token_identifier = self.get_contract_esdt_token_identifier(); require!( - actual_token_identifier == expected_token_identifier, + *actual_token_identifier == expected_token_identifier, "Wrong esdt token" ); @@ -86,7 +86,7 @@ pub trait FirstContract { let expected_token_identifier = self.get_contract_esdt_token_identifier(); require!( - actual_token_identifier == expected_token_identifier, + *actual_token_identifier == expected_token_identifier, "Wrong esdt token" ); @@ -107,7 +107,7 @@ pub trait FirstContract { let expected_token_identifier = self.get_contract_esdt_token_identifier(); require!( - actual_token_identifier == expected_token_identifier, + *actual_token_identifier == expected_token_identifier, "Wrong esdt token" ); @@ -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/execute-on-dest-esdt-issue-callback/child/src/lib.rs b/contracts/feature-tests/composability/execute-on-dest-esdt-issue-callback/child/src/lib.rs index e763a222af..dcb634f054 100644 --- a/contracts/feature-tests/composability/execute-on-dest-esdt-issue-callback/child/src/lib.rs +++ b/contracts/feature-tests/composability/execute-on-dest-esdt-issue-callback/child/src/lib.rs @@ -46,7 +46,7 @@ pub trait Child { #[callback] fn esdt_issue_callback(&self, #[call_result] _result: IgnoreValue) { let (token_identifier, _amount) = self.call_value().single_fungible_esdt(); - self.wrapped_egld_token_identifier().set(&token_identifier); + self.wrapped_egld_token_identifier().set(token_identifier); } // storage diff --git a/contracts/feature-tests/composability/forwarder-legacy/src/fwd_call_transf_exec_legacy.rs b/contracts/feature-tests/composability/forwarder-legacy/src/fwd_call_transf_exec_legacy.rs index e789e4644f..645f173b28 100644 --- a/contracts/feature-tests/composability/forwarder-legacy/src/fwd_call_transf_exec_legacy.rs +++ b/contracts/feature-tests/composability/forwarder-legacy/src/fwd_call_transf_exec_legacy.rs @@ -28,7 +28,7 @@ pub trait ForwarderTransferExecuteModule { self.vault_proxy() .contract(to) .accept_funds() - .payment((payment.token_identifier, 0, payment.amount)) + .single_esdt(&payment.token_identifier, 0, &payment.amount) .transfer_execute(); } diff --git a/contracts/feature-tests/composability/forwarder-legacy/src/fwd_esdt_legacy.rs b/contracts/feature-tests/composability/forwarder-legacy/src/fwd_esdt_legacy.rs index 6fa20793d8..7ba477b448 100644 --- a/contracts/feature-tests/composability/forwarder-legacy/src/fwd_esdt_legacy.rs +++ b/contracts/feature-tests/composability/forwarder-legacy/src/fwd_esdt_legacy.rs @@ -39,8 +39,8 @@ pub trait ForwarderEsdtModule: fwd_storage_legacy::ForwarderStorageModule { #[endpoint] fn send_esdt_with_fees(&self, to: ManagedAddress, percentage_fees: BigUint) { let (token_id, payment) = self.call_value().single_fungible_esdt(); - let fees = &payment * &percentage_fees / PERCENTAGE_TOTAL; - let amount_to_send = payment - fees; + let fees = &*payment * &percentage_fees / PERCENTAGE_TOTAL; + let amount_to_send = payment.clone() - fees; self.send().direct_esdt(&to, &token_id, 0, &amount_to_send); } 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..796bea5684 100644 --- a/contracts/feature-tests/composability/forwarder-raw/src/forwarder_raw.rs +++ b/contracts/feature-tests/composability/forwarder-raw/src/forwarder_raw.rs @@ -35,11 +35,11 @@ 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), + EgldOrEsdtTokenIdentifier::esdt(payment.token_identifier.clone()), payment.token_nonce, - payment.amount, + payment.amount.clone(), )); } } diff --git a/contracts/feature-tests/composability/forwarder-raw/src/forwarder_raw_async.rs b/contracts/feature-tests/composability/forwarder-raw/src/forwarder_raw_async.rs index 47240f3c52..df66f30a30 100644 --- a/contracts/feature-tests/composability/forwarder-raw/src/forwarder_raw_async.rs +++ b/contracts/feature-tests/composability/forwarder-raw/src/forwarder_raw_async.rs @@ -114,8 +114,8 @@ pub trait ForwarderRawAsync: super::forwarder_raw_common::ForwarderRawCommon { let (token, payment) = self.call_value().single_fungible_esdt(); self.forward_contract_call( to, - EgldOrEsdtTokenIdentifier::esdt(token), - payment, + EgldOrEsdtTokenIdentifier::esdt(token.clone()), + payment.clone(), endpoint_name, args, ) diff --git a/contracts/feature-tests/composability/forwarder/src/fwd_esdt.rs b/contracts/feature-tests/composability/forwarder/src/fwd_esdt.rs index a4dbaa28b1..425ca07053 100644 --- a/contracts/feature-tests/composability/forwarder/src/fwd_esdt.rs +++ b/contracts/feature-tests/composability/forwarder/src/fwd_esdt.rs @@ -42,8 +42,8 @@ pub trait ForwarderEsdtModule: fwd_storage::ForwarderStorageModule { #[endpoint] fn send_esdt_with_fees(&self, to: ManagedAddress, percentage_fees: BigUint) { let (token_id, payment) = self.call_value().single_fungible_esdt(); - let fees = &payment * &percentage_fees / PERCENTAGE_TOTAL; - let amount_to_send = payment - fees; + let fees = percentage_fees * &*payment / PERCENTAGE_TOTAL; + let amount_to_send = payment.clone() - fees; self.tx() .to(&to) diff --git a/contracts/feature-tests/composability/promises-features/src/fwd_call_promises_bt.rs b/contracts/feature-tests/composability/promises-features/src/fwd_call_promises_bt.rs index 2634e2c5ac..ba73843958 100644 --- a/contracts/feature-tests/composability/promises-features/src/fwd_call_promises_bt.rs +++ b/contracts/feature-tests/composability/promises-features/src/fwd_call_promises_bt.rs @@ -45,15 +45,19 @@ pub trait CallPromisesBackTransfersModule: common::CommonModule { } for esdt_transfer in &back_transfers.esdt_payments { - let (token, nonce, payment) = esdt_transfer.into_tuple(); - let esdt_token_id = EgldOrEsdtTokenIdentifier::esdt(token); - self.retrieve_funds_callback_event(&esdt_token_id, nonce, &payment); + let esdt_token_id = + EgldOrEsdtTokenIdentifier::esdt(esdt_transfer.token_identifier.clone()); + self.retrieve_funds_callback_event( + &esdt_token_id, + esdt_transfer.token_nonce, + &esdt_transfer.amount, + ); let _ = self.callback_data().push(&CallbackData { callback_name: ManagedBuffer::from(b"retrieve_funds_callback"), token_identifier: esdt_token_id, - token_nonce: nonce, - token_amount: payment, + token_nonce: esdt_transfer.token_nonce, + token_amount: esdt_transfer.amount.clone(), args: ManagedVec::new(), }); } diff --git a/contracts/feature-tests/composability/scenarios/forwarder_call_async_retrieve_egld.scen.json b/contracts/feature-tests/composability/scenarios/forwarder_call_async_retrieve_egld.scen.json index f9091ab5a9..ecfae9b375 100644 --- a/contracts/feature-tests/composability/scenarios/forwarder_call_async_retrieve_egld.scen.json +++ b/contracts/feature-tests/composability/scenarios/forwarder_call_async_retrieve_egld.scen.json @@ -84,7 +84,7 @@ "address": "sc:vault", "endpoint": "str:transferValueOnly", "topics": [ - "1000", + "", "sc:forwarder" ], "data": [ diff --git a/contracts/feature-tests/composability/scenarios/promises_call_async_retrieve_egld.scen.json b/contracts/feature-tests/composability/scenarios/promises_call_async_retrieve_egld.scen.json index bb8e199e91..e17b0fd7d5 100644 --- a/contracts/feature-tests/composability/scenarios/promises_call_async_retrieve_egld.scen.json +++ b/contracts/feature-tests/composability/scenarios/promises_call_async_retrieve_egld.scen.json @@ -83,7 +83,7 @@ "address": "sc:vault", "endpoint": "str:transferValueOnly", "topics": [ - "1000", + "", "sc:forwarder" ], "data": [ diff --git a/contracts/feature-tests/composability/vault/src/vault.rs b/contracts/feature-tests/composability/vault/src/vault.rs index 86ddbe31bb..d6f3feb81b 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, @@ -240,9 +240,9 @@ pub trait Vault { ); new_tokens.push(EsdtTokenPayment::new( - payment.token_identifier, + payment.token_identifier.clone(), new_token_nonce, - payment.amount, + payment.amount.clone(), )); } diff --git a/contracts/feature-tests/payable-features/scenarios/payable_token_5.scen.json b/contracts/feature-tests/payable-features/scenarios/payable_token_5.scen.json new file mode 100644 index 0000000000..6193d505e4 --- /dev/null +++ b/contracts/feature-tests/payable-features/scenarios/payable_token_5.scen.json @@ -0,0 +1,120 @@ +{ + "name": "payable", + "gasSchedule": "v3", + "steps": [ + { + "step": "setState", + "accounts": { + "sc:payable-features": { + "nonce": "0", + "balance": "0", + "code": "mxsc:../output/payable-features.mxsc.json", + "codeMetadata": "0x0000" + }, + "address:an-account": { + "nonce": "0", + "balance": "1,000,000,000,000", + "esdt": { + "str:PAYABLE-FEATURES-TOKEN": "1,000,000,000,000", + "str:OTHER-TOKEN": "1,000,000,000,000" + } + } + } + }, + { + "step": "scCall", + "id": "payable_token_1.1", + "tx": { + "from": "address:an-account", + "to": "sc:payable-features", + "function": "payable_token_1", + "arguments": [], + "gasLimit": "50,000,000", + "gasPrice": "0" + }, + "expect": { + "out": [], + "status": "4", + "message": "str:function expects single ESDT payment", + "logs": "*", + "gas": "*", + "refund": "*" + } + }, + { + "step": "scCall", + "id": "payable_token_1.2", + "tx": { + "from": "address:an-account", + "to": "sc:payable-features", + "egldValue": "5", + "function": "payable_token_1", + "arguments": [], + "gasLimit": "50,000,000", + "gasPrice": "0" + }, + "expect": { + "out": [], + "status": "4", + "message": "str:function expects single ESDT payment", + "logs": "*", + "gas": "*", + "refund": "*" + } + }, + { + "step": "scCall", + "id": "payable_token_1.3", + "tx": { + "from": "address:an-account", + "to": "sc:payable-features", + "esdtValue": [ + { + "tokenIdentifier": "str:PAYABLE-FEATURES-TOKEN", + "value": "100" + } + ], + "function": "payable_token_1", + "arguments": [], + "gasLimit": "50,000,000", + "gasPrice": "0" + }, + "expect": { + "out": [ + "0x64", + "0x50415941424c452d46454154555245532d544f4b454e" + ], + "status": "0", + "logs": "*", + "gas": "*", + "refund": "*" + } + }, + { + "step": "scCall", + "id": "payable_token_1.4", + "tx": { + "from": "address:an-account", + "to": "sc:payable-features", + "esdtValue": [ + { + "tokenIdentifier": "str:OTHER-TOKEN", + "value": "100" + } + ], + "function": "payable_token_1", + "arguments": [], + "gasLimit": "50,000,000", + "gasPrice": "0" + }, + "expect": { + "out": [], + "status": "4", + "message": "str:bad call value token provided", + "logs": "*", + "gas": "*", + "refund": "*" + } + } + ] +} \ No newline at end of file diff --git a/contracts/feature-tests/payable-features/src/payable_features.rs b/contracts/feature-tests/payable-features/src/payable_features.rs index d8296f8592..cf418efc0c 100644 --- a/contracts/feature-tests/payable-features/src/payable_features.rs +++ b/contracts/feature-tests/payable-features/src/payable_features.rs @@ -1,7 +1,9 @@ #![no_std] #![allow(clippy::type_complexity)] -multiversx_sc::imports!(); +use multiversx_sc::imports::*; + +pub mod payable_features_proxy; /// Contract that only tests the call value features, /// i.e. the framework/Arwen functionality for accepting EGLD and ESDT payments. @@ -35,7 +37,7 @@ pub trait PayableFeatures { #[payable("*")] fn payment_array_3(&self) -> MultiValue3 { let [payment_a, payment_b, payment_c] = self.call_value().multi_esdt(); - (payment_a, payment_b, payment_c).into() + (payment_a.clone(), payment_b.clone(), payment_c.clone()).into() } #[endpoint] @@ -129,7 +131,7 @@ pub trait PayableFeatures { &self, #[payment] payment: BigUint, ) -> MultiValue2 { - let token = self.call_value().single_esdt().token_identifier; + let token = self.call_value().single_esdt().token_identifier.clone(); (payment, token).into() } @@ -140,14 +142,14 @@ pub trait PayableFeatures { #[payment_token] token: EgldOrEsdtTokenIdentifier, ) -> MultiValue2 { let payment = self.call_value().single_esdt(); - (payment.amount, token).into() + (payment.amount.clone(), token).into() } #[endpoint] #[payable("PAYABLE-FEATURES-TOKEN")] fn payable_token_4(&self) -> MultiValue2 { - let payment = self.call_value().single_esdt().amount; - let token = self.call_value().single_esdt().token_identifier; + let payment = self.call_value().single_esdt().amount.clone(); + let token = self.call_value().single_esdt().token_identifier.clone(); (payment, token).into() } } diff --git a/contracts/feature-tests/payable-features/src/payable_features_proxy.rs b/contracts/feature-tests/payable-features/src/payable_features_proxy.rs new file mode 100644 index 0000000000..7d6e020c89 --- /dev/null +++ b/contracts/feature-tests/payable-features/src/payable_features_proxy.rs @@ -0,0 +1,184 @@ +// Code generated by the multiversx-sc proxy generator. DO NOT EDIT. + +//////////////////////////////////////////////////// +////////////////// AUTO-GENERATED ////////////////// +//////////////////////////////////////////////////// + +#![allow(dead_code)] +#![allow(clippy::all)] + +use multiversx_sc::proxy_imports::*; + +pub struct PayableFeaturesProxy; + +impl TxProxyTrait for PayableFeaturesProxy +where + Env: TxEnv, + From: TxFrom, + To: TxTo, + Gas: TxGas, +{ + type TxProxyMethods = PayableFeaturesProxyMethods; + + fn proxy_methods(self, tx: Tx) -> Self::TxProxyMethods { + PayableFeaturesProxyMethods { wrapped_tx: tx } + } +} + +pub struct PayableFeaturesProxyMethods +where + Env: TxEnv, + From: TxFrom, + To: TxTo, + Gas: TxGas, +{ + wrapped_tx: Tx, +} + +#[rustfmt::skip] +impl PayableFeaturesProxyMethods +where + Env: TxEnv, + Env::Api: VMApi, + From: TxFrom, + Gas: TxGas, +{ + pub fn init( + self, + ) -> TxTypedDeploy { + self.wrapped_tx + .payment(NotPayable) + .raw_deploy() + .original_result() + } +} + +#[rustfmt::skip] +impl PayableFeaturesProxyMethods +where + Env: TxEnv, + Env::Api: VMApi, + From: TxFrom, + To: TxTo, + Gas: TxGas, +{ + pub fn echo_call_value( + self, + ) -> TxTypedCall, ManagedVec>>> { + self.wrapped_tx + .raw_call("echo_call_value") + .original_result() + } + + pub fn payment_multiple( + self, + ) -> TxTypedCall>> { + self.wrapped_tx + .raw_call("payment_multiple") + .original_result() + } + + pub fn payment_array_3( + self, + ) -> TxTypedCall, EsdtTokenPayment, EsdtTokenPayment>> { + self.wrapped_tx + .raw_call("payment_array_3") + .original_result() + } + + pub fn payable_any_1( + self, + ) -> TxTypedCall, EgldOrEsdtTokenIdentifier>> { + self.wrapped_tx + .raw_call("payable_any_1") + .original_result() + } + + pub fn payable_any_2( + self, + ) -> TxTypedCall, EgldOrEsdtTokenIdentifier>> { + self.wrapped_tx + .raw_call("payable_any_2") + .original_result() + } + + pub fn payable_any_3( + self, + ) -> TxTypedCall, EgldOrEsdtTokenIdentifier>> { + self.wrapped_tx + .raw_call("payable_any_3") + .original_result() + } + + pub fn payable_any_4( + self, + ) -> TxTypedCall, EgldOrEsdtTokenIdentifier>> { + self.wrapped_tx + .raw_call("payable_any_4") + .original_result() + } + + pub fn payable_egld_1( + self, + ) -> TxTypedCall, EgldOrEsdtTokenIdentifier>> { + self.wrapped_tx + .raw_call("payable_egld_1") + .original_result() + } + + pub fn payable_egld_2( + self, + ) -> TxTypedCall, EgldOrEsdtTokenIdentifier>> { + self.wrapped_tx + .raw_call("payable_egld_2") + .original_result() + } + + pub fn payable_egld_3( + self, + ) -> TxTypedCall, EgldOrEsdtTokenIdentifier>> { + self.wrapped_tx + .raw_call("payable_egld_3") + .original_result() + } + + pub fn payable_egld_4( + self, + ) -> TxTypedCall, EgldOrEsdtTokenIdentifier>> { + self.wrapped_tx + .raw_call("payable_egld_4") + .original_result() + } + + pub fn payable_token_1( + self, + ) -> TxTypedCall, EgldOrEsdtTokenIdentifier>> { + self.wrapped_tx + .raw_call("payable_token_1") + .original_result() + } + + pub fn payable_token_2( + self, + ) -> TxTypedCall, TokenIdentifier>> { + self.wrapped_tx + .raw_call("payable_token_2") + .original_result() + } + + pub fn payable_token_3( + self, + ) -> TxTypedCall, EgldOrEsdtTokenIdentifier>> { + self.wrapped_tx + .raw_call("payable_token_3") + .original_result() + } + + pub fn payable_token_4( + self, + ) -> TxTypedCall, TokenIdentifier>> { + self.wrapped_tx + .raw_call("payable_token_4") + .original_result() + } +} diff --git a/contracts/feature-tests/payable-features/tests/payable_blackbox_test.rs b/contracts/feature-tests/payable-features/tests/payable_blackbox_test.rs index 44aa98c1b5..b56dc46aaa 100644 --- a/contracts/feature-tests/payable-features/tests/payable_blackbox_test.rs +++ b/contracts/feature-tests/payable-features/tests/payable_blackbox_test.rs @@ -1,6 +1,13 @@ use multiversx_sc_scenario::imports::*; +use payable_features::payable_features_proxy; -const PF_PATH_EXPR: &str = "mxsc:output/payable-features.mxsc.json"; +const PF_PATH_EXPR: MxscPath = MxscPath::new("output/payable-features.mxsc.json"); +const PAYABLE_FEATURES_ADDRESS: TestSCAddress = TestSCAddress::new("payable-features"); +const USER: TestAddress = TestAddress::new("an-account"); +const TOKEN_1: TestTokenIdentifier = TestTokenIdentifier::new("TOK-000001"); +const TOKEN_2: TestTokenIdentifier = TestTokenIdentifier::new("TOK-000002"); +const TOKEN_3: TestTokenIdentifier = TestTokenIdentifier::new("TOK-000003"); +const SFT: TestTokenIdentifier = TestTokenIdentifier::new("SFT-123"); fn world() -> ScenarioWorld { let mut blockchain = ScenarioWorld::new(); @@ -13,33 +20,41 @@ fn world() -> ScenarioWorld { #[test] fn payable_multi() { let mut world = world(); - let pf_code = world.code_expression(PF_PATH_EXPR); world - .set_state_step( - SetStateStep::new() - .put_account("sc:payable-features", Account::new().code(pf_code)) - .put_account( - "address:an-account", - Account::new() - .balance("10000") - .esdt_balance("str:TOK-000001", "1000") - .esdt_balance("str:TOK-000002", "500") - .esdt_balance("str:TOK-000003", "500") - .esdt_nft_balance("str:SFT-123", 5u32, 10u32, Option::<()>::None) - ), - ) - .sc_call( - ScCallStep::new() - .from("address:an-account") - .to("sc:payable-features") - .function("echo_call_value") - .esdt_transfer("str:TOK-000001", 0, "100") - .esdt_transfer("str:TOK-000002", 0, "400") - .expect( - TxExpect::ok() - .result("0") - .result("nested:str:TOK-000001|u64:0|biguint:100|nested:str:TOK-000002|u64:0|biguint:400") - ), - ); + .account(USER) + .balance(10000) + .esdt_balance(TOKEN_1, 1000) + .esdt_balance(TOKEN_2, 500) + .esdt_balance(TOKEN_3, 500) + .esdt_nft_balance(SFT, 5, 10, ()); + + world + .tx() + .from(USER) + .typed(payable_features_proxy::PayableFeaturesProxy) + .init() + .new_address(PAYABLE_FEATURES_ADDRESS) + .code(PF_PATH_EXPR) + .run(); + + let result = world + .tx() + .from(USER) + .to(PAYABLE_FEATURES_ADDRESS) + .typed(payable_features_proxy::PayableFeaturesProxy) + .echo_call_value() + .esdt(TestEsdtTransfer(TOKEN_1, 0, 100)) + .esdt(TestEsdtTransfer(TOKEN_2, 0, 400)) + .returns(ReturnsResultUnmanaged) + .run(); + + assert_eq!(result.0 .0, RustBigUint::from(0u32)); + assert_eq!( + result.0 .1, + vec![ + EsdtTokenPayment::new(TOKEN_1.to_token_identifier(), 0, BigUint::from(100u32)), + EsdtTokenPayment::new(TOKEN_2.to_token_identifier(), 0, BigUint::from(400u32)) + ] + ); } diff --git a/contracts/feature-tests/payable-features/tests/payable_scenario_go_test.rs b/contracts/feature-tests/payable-features/tests/payable_scenario_go_test.rs index 58db78cf8f..a3ababd9c7 100644 --- a/contracts/feature-tests/payable-features/tests/payable_scenario_go_test.rs +++ b/contracts/feature-tests/payable-features/tests/payable_scenario_go_test.rs @@ -78,3 +78,8 @@ fn payable_token_3_go() { fn payable_token_4_go() { world().run("scenarios/payable_token_4.scen.json"); } + +#[test] +fn payable_token_5_go() { + world().run("scenarios/payable_token_5.scen.json"); +} diff --git a/contracts/feature-tests/payable-features/tests/payable_scenario_rs_test.rs b/contracts/feature-tests/payable-features/tests/payable_scenario_rs_test.rs index 4e88c1cd75..01b0ea567b 100644 --- a/contracts/feature-tests/payable-features/tests/payable_scenario_rs_test.rs +++ b/contracts/feature-tests/payable-features/tests/payable_scenario_rs_test.rs @@ -84,3 +84,8 @@ fn payable_token_3_rs() { fn payable_token_4_rs() { world().run("scenarios/payable_token_4.scen.json"); } + +#[test] +fn payable_token_5_rs() { + world().run("scenarios/payable_token_5.scen.json"); +} diff --git a/contracts/feature-tests/rust-testing-framework-tester/src/lib.rs b/contracts/feature-tests/rust-testing-framework-tester/src/lib.rs index ffc411dad0..9d7be05858 100644 --- a/contracts/feature-tests/rust-testing-framework-tester/src/lib.rs +++ b/contracts/feature-tests/rust-testing-framework-tester/src/lib.rs @@ -71,7 +71,7 @@ pub trait RustTestingFrameworkTester: dummy_module::DummyModule { #[endpoint] fn receive_esdt(&self) -> (TokenIdentifier, BigUint) { let payment = self.call_value().single_esdt(); - (payment.token_identifier, payment.amount) + (payment.token_identifier.clone(), payment.amount.clone()) } #[payable("*")] @@ -84,7 +84,7 @@ pub trait RustTestingFrameworkTester: dummy_module::DummyModule { #[endpoint] fn receive_esdt_half(&self) { let payment = self.call_value().single_esdt(); - let amount = payment.amount / 2u32; + let amount = &payment.amount / 2u32; self.tx() .to(ToCaller) diff --git a/contracts/feature-tests/use-module/src/token_merge_mod_impl.rs b/contracts/feature-tests/use-module/src/token_merge_mod_impl.rs index b5d7711481..04f7b9cc7d 100644 --- a/contracts/feature-tests/use-module/src/token_merge_mod_impl.rs +++ b/contracts/feature-tests/use-module/src/token_merge_mod_impl.rs @@ -55,7 +55,7 @@ pub trait TokenMergeModImpl: ) -> ManagedVec { let payment = self.call_value().single_esdt(); let attributes_creator = DefaultMergedAttributesWrapper::new(); - self.split_token_partial(payment, tokens_to_remove, &attributes_creator) + self.split_token_partial(payment.clone(), tokens_to_remove, &attributes_creator) } } diff --git a/contracts/modules/src/bonding_curve/utils/owner_endpoints.rs b/contracts/modules/src/bonding_curve/utils/owner_endpoints.rs index 382e1fbc28..1c51d47905 100644 --- a/contracts/modules/src/bonding_curve/utils/owner_endpoints.rs +++ b/contracts/modules/src/bonding_curve/utils/owner_endpoints.rs @@ -90,11 +90,14 @@ pub trait OwnerEndpointsModule: storage::StorageModule + events::EventsModule { + PartialEq + Default, { - let (identifier, nonce, amount) = self.call_value().single_esdt().into_tuple(); + let esdt_payment = self.call_value().single_esdt(); + let identifier = &esdt_payment.token_identifier; + let nonce = esdt_payment.token_nonce; + let amount = &esdt_payment.amount; let caller = self.blockchain().get_caller(); let mut set_payment = EgldOrEsdtTokenIdentifier::egld(); - if self.bonding_curve(&identifier).is_empty() { + if self.bonding_curve(identifier).is_empty() { match payment_token { OptionalValue::Some(token) => set_payment = EgldOrEsdtTokenIdentifier::esdt(token), OptionalValue::None => { @@ -102,27 +105,27 @@ pub trait OwnerEndpointsModule: storage::StorageModule + events::EventsModule { }, }; } - if self.token_details(&identifier).is_empty() { + if self.token_details(identifier).is_empty() { let nonces = ManagedVec::from_single_item(nonce); - self.token_details(&identifier).set(&TokenOwnershipData { + self.token_details(identifier).set(&TokenOwnershipData { token_nonces: nonces, owner: caller.clone(), }); } else { - let mut details = self.token_details(&identifier).get(); + let mut details = self.token_details(identifier).get(); require!( details.owner == caller, "The token was already deposited by another address" ); if !details.token_nonces.contains(&nonce) { details.token_nonces.push(nonce); - self.token_details(&identifier).set(&details); + self.token_details(identifier).set(&details); } } - self.set_curve_storage::(&identifier, amount.clone(), set_payment); + self.set_curve_storage::(identifier, amount.clone(), set_payment); self.owned_tokens(&caller).insert(identifier.clone()); - self.nonce_amount(&identifier, nonce) + self.nonce_amount(identifier, nonce) .update(|current_amount| *current_amount += amount); } diff --git a/contracts/modules/src/bonding_curve/utils/user_endpoints.rs b/contracts/modules/src/bonding_curve/utils/user_endpoints.rs index f627d26256..a51236512a 100644 --- a/contracts/modules/src/bonding_curve/utils/user_endpoints.rs +++ b/contracts/modules/src/bonding_curve/utils/user_endpoints.rs @@ -21,11 +21,14 @@ pub trait UserEndpointsModule: storage::StorageModule + events::EventsModule { + PartialEq + Default, { - let (offered_token, nonce, sell_amount) = self.call_value().single_esdt().into_tuple(); - let _ = self.check_owned_return_payment_token::(&offered_token, &sell_amount); + let esdt_payment = self.call_value().single_esdt(); + let offered_token = &esdt_payment.token_identifier; + let nonce = esdt_payment.token_nonce; + let sell_amount = &esdt_payment.amount; + let _ = self.check_owned_return_payment_token::(offered_token, sell_amount); let (calculated_price, payment_token) = - self.bonding_curve(&offered_token).update(|buffer| { + self.bonding_curve(offered_token).update(|buffer| { let serializer = ManagedSerializer::new(); let mut bonding_curve: BondingCurve = @@ -35,9 +38,9 @@ pub trait UserEndpointsModule: storage::StorageModule + events::EventsModule { bonding_curve.sell_availability, "Selling is not available on this token" ); - let price = self.compute_sell_price::(&offered_token, &sell_amount); + let price = self.compute_sell_price::(offered_token, sell_amount); bonding_curve.payment.amount -= &price; - bonding_curve.arguments.balance += &sell_amount; + bonding_curve.arguments.balance += sell_amount; let payment_token = bonding_curve.payment_token(); *buffer = serializer.top_encode_to_managed_buffer(&bonding_curve); (price, payment_token) @@ -45,7 +48,7 @@ pub trait UserEndpointsModule: storage::StorageModule + events::EventsModule { let caller = self.blockchain().get_caller(); - self.nonce_amount(&offered_token, nonce) + self.nonce_amount(offered_token, nonce) .update(|val| *val += sell_amount); self.tx() @@ -53,7 +56,7 @@ pub trait UserEndpointsModule: storage::StorageModule + events::EventsModule { .egld_or_single_esdt(&payment_token, 0u64, &calculated_price) .transfer(); - self.token_details(&offered_token) + self.token_details(offered_token) .update(|details| details.add_nonce(nonce)); self.sell_token_event(&caller, &calculated_price); diff --git a/contracts/modules/src/default_issue_callbacks.rs b/contracts/modules/src/default_issue_callbacks.rs index 6edd7abeec..8e9e1c6e90 100644 --- a/contracts/modules/src/default_issue_callbacks.rs +++ b/contracts/modules/src/default_issue_callbacks.rs @@ -35,7 +35,7 @@ pub trait DefaultIssueCallbacksModule { let key = StorageKey::from(storage_key); match result { ManagedAsyncCallResult::Ok(()) => { - let token_id = self.call_value().single_esdt().token_identifier; + let token_id = self.call_value().single_esdt().token_identifier.clone(); storage_set(key.as_ref(), &TokenMapperState::Token(token_id)); }, ManagedAsyncCallResult::Err(_) => { diff --git a/contracts/modules/src/esdt.rs b/contracts/modules/src/esdt.rs index ea977f53be..42314e9608 100644 --- a/contracts/modules/src/esdt.rs +++ b/contracts/modules/src/esdt.rs @@ -84,7 +84,9 @@ pub trait EsdtModule { fn nft_create(&self, amount: &BigUint, attributes: &T) -> u64 { let token_id = self.token_id().get(); let empty_buffer = ManagedBuffer::new(); - let empty_vec = ManagedVec::from_handle(empty_buffer.get_handle()); + + // sneakily reuses the same handle + let empty_vec = unsafe { ManagedRef::wrap_handle(empty_buffer.get_handle()) }; self.send().esdt_nft_create( &token_id, 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..4d407cf593 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( @@ -435,7 +435,7 @@ pub trait GovernanceModule: payment.token_identifier == self.governance_token_id().get(), "Only Governance token accepted as payment" ); - payment + payment.clone() } fn require_valid_proposal_id(&self, proposal_id: usize) { 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/contracts/modules/src/token_merge/mod.rs b/contracts/modules/src/token_merge/mod.rs index b940980dfe..dad6665c0d 100644 --- a/contracts/modules/src/token_merge/mod.rs +++ b/contracts/modules/src/token_merge/mod.rs @@ -69,7 +69,7 @@ pub trait TokenMergeModule: } for single_token_instance in single_tokens { - all_merged_instances.add_or_update_instance(single_token_instance); + all_merged_instances.add_or_update_instance(single_token_instance.clone()); } let merged_token_payment = diff --git a/data/codec/src/impl_for_types/impl_phantom.rs b/data/codec/src/impl_for_types/impl_phantom.rs index 6036152f02..60087753b6 100644 --- a/data/codec/src/impl_for_types/impl_phantom.rs +++ b/data/codec/src/impl_for_types/impl_phantom.rs @@ -8,7 +8,6 @@ use crate::{ /// Empty structure with an empty bytes representation. Equivalent to `false`, `0` or `[u8; 0]`, but more explicit. /// /// Note: the unit type `()` would have naturally fit this role, but we decided to make the unit type multi-value only. - impl TopEncode for PhantomData { #[inline] fn top_encode_or_handle_err(&self, output: O, _h: H) -> Result<(), H::HandledErr> diff --git a/data/codec/src/single/nested_de_input_slice.rs b/data/codec/src/single/nested_de_input_slice.rs index ce399a8de9..b0dd0eed51 100644 --- a/data/codec/src/single/nested_de_input_slice.rs +++ b/data/codec/src/single/nested_de_input_slice.rs @@ -1,7 +1,7 @@ use crate::{DecodeError, DecodeErrorHandler, NestedDecode, NestedDecodeInput}; /// A nested decode buffer implementation on referenced data. -impl<'a> NestedDecodeInput for &'a [u8] { +impl NestedDecodeInput for &[u8] { fn remaining_len(&self) -> usize { self.len() } diff --git a/data/codec/src/single/top_en_output.rs b/data/codec/src/single/top_en_output.rs index 4f955ca2f2..b2d2618d39 100644 --- a/data/codec/src/single/top_en_output.rs +++ b/data/codec/src/single/top_en_output.rs @@ -5,7 +5,6 @@ use crate::{ use alloc::vec::Vec; /// Specifies objects that can receive the result of a TopEncode computation. - /// in principle from NestedEncode performed on nested items. /// /// All methods consume the object, so they can only be called once. diff --git a/framework/base/src/api/managed_types.rs b/framework/base/src/api/managed_types.rs index 3562020b95..1322ede5ee 100644 --- a/framework/base/src/api/managed_types.rs +++ b/framework/base/src/api/managed_types.rs @@ -8,6 +8,7 @@ mod managed_map_api; mod managed_type_api; mod managed_type_api_impl; mod static_var_api; +mod static_var_api_flags; mod token_identifier_util; pub use big_float_api::*; @@ -19,3 +20,4 @@ pub use managed_map_api::*; pub use managed_type_api::*; pub use managed_type_api_impl::*; pub use static_var_api::*; +pub use static_var_api_flags::StaticVarApiFlags; diff --git a/framework/base/src/api/managed_types/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/base/src/api/managed_types/static_var_api.rs b/framework/base/src/api/managed_types/static_var_api.rs index 8eaf474ef3..9044cd6b06 100644 --- a/framework/base/src/api/managed_types/static_var_api.rs +++ b/framework/base/src/api/managed_types/static_var_api.rs @@ -1,6 +1,6 @@ use crate::types::LockableStaticBuffer; -use super::RawHandle; +use super::{RawHandle, StaticVarApiFlags}; pub trait StaticVarApi { type StaticVarApiImpl: StaticVarApiImpl; @@ -24,13 +24,21 @@ pub trait StaticVarApiImpl { fn get_num_arguments(&self) -> i32; - fn set_call_value_egld_handle(&self, handle: RawHandle); - - fn get_call_value_egld_handle(&self) -> RawHandle; - - fn set_call_value_multi_esdt_handle(&self, handle: RawHandle); - - fn get_call_value_multi_esdt_handle(&self) -> RawHandle; + fn set_flags(&self, flags: StaticVarApiFlags); + + fn get_flags(&self) -> StaticVarApiFlags; + + /// Returns true if the flag is set, false if is default (false). + /// + /// If the flag is unset (false), will set it. + fn flag_is_set_or_update(&self, flag: StaticVarApiFlags) -> bool { + let mut current_flags = self.get_flags(); + let contains_flag = current_flags.check_and_set(flag); + if !contains_flag { + self.set_flags(current_flags); + } + contains_flag + } fn is_scaling_factor_cached(&self, decimals: usize) -> bool; diff --git a/framework/base/src/api/managed_types/static_var_api_flags.rs b/framework/base/src/api/managed_types/static_var_api_flags.rs new file mode 100644 index 0000000000..1c9e153e69 --- /dev/null +++ b/framework/base/src/api/managed_types/static_var_api_flags.rs @@ -0,0 +1,53 @@ +use bitflags::bitflags; + +bitflags! { + #[derive(Clone, Copy, Debug, PartialEq, Eq)] + pub struct StaticVarApiFlags: u8 { + const NONE = 0b00000000; + const CALL_VALUE_EGLD_INITIALIZED = 0b00000001; + const CALL_VALUE_EGLD_MULTI_INITIALIZED = 0b00000010; + const CALL_VALUE_MULTI_ESDT_INITIALIZED = 0b00000100; + const CALL_VALUE_ALL_INITIALIZED = 0b00001000; + } +} + +impl StaticVarApiFlags { + pub fn check_and_set(&mut self, other: StaticVarApiFlags) -> bool { + let contains_flag = self.contains(other); + if !contains_flag { + *self |= other; + } + contains_flag + } +} + +#[cfg(test)] +pub mod tests { + use super::StaticVarApiFlags; + + #[test] + fn test_check_and_set() { + let mut current = StaticVarApiFlags::NONE; + + assert!(current.check_and_set(StaticVarApiFlags::NONE)); + assert_eq!(current, StaticVarApiFlags::NONE); + + assert!(!current.check_and_set(StaticVarApiFlags::CALL_VALUE_EGLD_INITIALIZED)); + assert_eq!(current, StaticVarApiFlags::CALL_VALUE_EGLD_INITIALIZED); + assert!(current.check_and_set(StaticVarApiFlags::CALL_VALUE_EGLD_INITIALIZED)); + assert_eq!(current, StaticVarApiFlags::CALL_VALUE_EGLD_INITIALIZED); + + assert!(!current.check_and_set(StaticVarApiFlags::CALL_VALUE_ALL_INITIALIZED)); + assert_eq!( + current, + StaticVarApiFlags::CALL_VALUE_EGLD_INITIALIZED + | StaticVarApiFlags::CALL_VALUE_ALL_INITIALIZED + ); + assert!(current.check_and_set(StaticVarApiFlags::CALL_VALUE_ALL_INITIALIZED)); + assert_eq!( + current, + StaticVarApiFlags::CALL_VALUE_EGLD_INITIALIZED + | StaticVarApiFlags::CALL_VALUE_ALL_INITIALIZED + ); + } +} diff --git a/framework/base/src/api/uncallable/static_var_api_uncallable.rs b/framework/base/src/api/uncallable/static_var_api_uncallable.rs index 1da3c772cf..005a302e53 100644 --- a/framework/base/src/api/uncallable/static_var_api_uncallable.rs +++ b/framework/base/src/api/uncallable/static_var_api_uncallable.rs @@ -1,5 +1,5 @@ use crate::{ - api::{RawHandle, StaticVarApi, StaticVarApiImpl}, + api::{RawHandle, StaticVarApi, StaticVarApiFlags, StaticVarApiImpl}, types::LockableStaticBuffer, }; @@ -41,19 +41,11 @@ impl StaticVarApiImpl for UncallableApi { unreachable!() } - fn set_call_value_egld_handle(&self, _handle: RawHandle) { + fn set_flags(&self, _flags: StaticVarApiFlags) { unreachable!() } - fn get_call_value_egld_handle(&self) -> RawHandle { - unreachable!() - } - - fn set_call_value_multi_esdt_handle(&self, _handle: RawHandle) { - unreachable!() - } - - fn get_call_value_multi_esdt_handle(&self) -> RawHandle { + fn get_flags(&self) -> StaticVarApiFlags { unreachable!() } diff --git a/framework/base/src/contract_base/wrappers/blockchain_wrapper.rs b/framework/base/src/contract_base/wrappers/blockchain_wrapper.rs index c499c9f663..e769bb69c7 100644 --- a/framework/base/src/contract_base/wrappers/blockchain_wrapper.rs +++ b/framework/base/src/contract_base/wrappers/blockchain_wrapper.rs @@ -11,8 +11,8 @@ use crate::{ storage::{self}, types::{ BackTransfers, BigUint, CodeMetadata, EgldOrEsdtTokenIdentifier, EsdtLocalRoleFlags, - EsdtTokenData, EsdtTokenType, ManagedAddress, ManagedBuffer, ManagedByteArray, ManagedType, - ManagedVec, TokenIdentifier, + EsdtTokenData, EsdtTokenType, ManagedAddress, ManagedBuffer, ManagedByteArray, + ManagedRefMut, ManagedType, ManagedVec, TokenIdentifier, }, }; @@ -49,9 +49,11 @@ where #[inline] pub fn get_caller(&self) -> ManagedAddress { - let handle: A::ManagedBufferHandle = use_raw_handle(A::static_var_api_impl().next_handle()); - A::blockchain_api_impl().load_caller_managed(handle.clone()); - ManagedAddress::from_handle(handle) + unsafe { + let result = ManagedAddress::new_uninit(); + A::blockchain_api_impl().load_caller_managed(result.get_handle()); + result + } } #[deprecated(since = "0.41.0", note = "Please use method `get_sc_address` instead.")] @@ -63,16 +65,20 @@ where #[inline] pub fn get_sc_address(&self) -> ManagedAddress { - let handle: A::ManagedBufferHandle = use_raw_handle(A::static_var_api_impl().next_handle()); - A::blockchain_api_impl().load_sc_address_managed(handle.clone()); - ManagedAddress::from_handle(handle) + unsafe { + let result = ManagedAddress::new_uninit(); + A::blockchain_api_impl().load_sc_address_managed(result.get_handle()); + result + } } #[inline] pub fn get_owner_address(&self) -> ManagedAddress { - let handle: A::ManagedBufferHandle = use_raw_handle(A::static_var_api_impl().next_handle()); - A::blockchain_api_impl().load_owner_address_managed(handle.clone()); - ManagedAddress::from_handle(handle) + unsafe { + let result = ManagedAddress::new_uninit(); + A::blockchain_api_impl().load_owner_address_managed(result.get_handle()); + result + } } pub fn check_caller_is_owner(&self) { @@ -123,16 +129,20 @@ where #[cfg(feature = "alloc")] #[inline] pub fn get_balance_legacy(&self, address: &crate::types::Address) -> BigUint { - let handle: A::BigIntHandle = use_raw_handle(A::static_var_api_impl().next_handle()); - A::blockchain_api_impl().load_balance_legacy(handle.clone(), address); - BigUint::from_handle(handle) + unsafe { + let result = BigUint::new_uninit(); + A::blockchain_api_impl().load_balance_legacy(result.get_handle(), address); + result + } } #[inline] pub fn get_balance(&self, address: &ManagedAddress) -> BigUint { - let handle: A::BigIntHandle = use_raw_handle(A::static_var_api_impl().next_handle()); - A::blockchain_api_impl().load_balance(handle.clone(), address.get_handle()); - BigUint::from_handle(handle) + unsafe { + let result = BigUint::new_uninit(); + A::blockchain_api_impl().load_balance(result.get_handle(), address.get_handle()); + result + } } #[inline] @@ -141,7 +151,10 @@ where A::blockchain_api_impl() .managed_get_code_metadata(address.get_handle(), mbuf_temp_1.clone()); let mut buffer = [0u8; 2]; - ManagedBuffer::::from_handle(mbuf_temp_1).load_to_byte_array(&mut buffer); + unsafe { + ManagedRefMut::<'static, A, ManagedBuffer>::wrap_handle(mbuf_temp_1) + .load_to_byte_array(&mut buffer); + } CodeMetadata::from(buffer) } @@ -173,9 +186,11 @@ where #[inline] pub fn get_state_root_hash(&self) -> ManagedByteArray { - let handle: A::ManagedBufferHandle = use_raw_handle(A::static_var_api_impl().next_handle()); - A::blockchain_api_impl().load_state_root_hash_managed(handle.clone()); - ManagedByteArray::from_handle(handle) + unsafe { + let result = ManagedByteArray::new_uninit(); + A::blockchain_api_impl().load_state_root_hash_managed(result.get_handle()); + result + } } #[deprecated(since = "0.41.0", note = "Please use method `get_tx_hash` instead.")] @@ -187,9 +202,11 @@ where #[inline] pub fn get_tx_hash(&self) -> ManagedByteArray { - let handle: A::ManagedBufferHandle = use_raw_handle(A::static_var_api_impl().next_handle()); - A::blockchain_api_impl().load_tx_hash_managed(handle.clone()); - ManagedByteArray::from_handle(handle) + unsafe { + let result = ManagedByteArray::new_uninit(); + A::blockchain_api_impl().load_tx_hash_managed(result.get_handle()); + result + } } #[inline] @@ -229,9 +246,11 @@ where #[inline] pub fn get_block_random_seed(&self) -> ManagedByteArray { - let handle: A::ManagedBufferHandle = use_raw_handle(A::static_var_api_impl().next_handle()); - A::blockchain_api_impl().load_block_random_seed_managed(handle.clone()); - ManagedByteArray::from_handle(handle) + unsafe { + let result = ManagedByteArray::new_uninit(); + A::blockchain_api_impl().load_block_random_seed_managed(result.get_handle()); + result + } } #[inline] @@ -266,9 +285,11 @@ where #[inline] pub fn get_prev_block_random_seed(&self) -> ManagedByteArray { - let handle: A::ManagedBufferHandle = use_raw_handle(A::static_var_api_impl().next_handle()); - A::blockchain_api_impl().load_prev_block_random_seed_managed(handle.clone()); - ManagedByteArray::from_handle(handle) + unsafe { + let result = ManagedByteArray::new_uninit(); + A::blockchain_api_impl().load_prev_block_random_seed_managed(result.get_handle()); + result + } } #[inline] @@ -288,14 +309,16 @@ where token_id: &TokenIdentifier, nonce: u64, ) -> BigUint { - let result_handle: A::BigIntHandle = use_raw_handle(A::static_var_api_impl().next_handle()); - A::blockchain_api_impl().load_esdt_balance( - address.get_handle(), - token_id.get_handle(), - nonce, - result_handle.clone(), - ); - BigUint::from_handle(result_handle) + unsafe { + let result = BigUint::new_uninit(); + A::blockchain_api_impl().load_esdt_balance( + address.get_handle(), + token_id.get_handle(), + nonce, + result.get_handle(), + ); + result + } } pub fn get_esdt_token_data( @@ -346,16 +369,18 @@ where let _ = managed_api_impl.mb_load_slice(properties_handle, 0, &mut properties_bytes[..]); let frozen = esdt_is_frozen(&properties_bytes); - EsdtTokenData { - token_type, - amount: BigUint::from_raw_handle(value_handle.get_raw_handle()), - frozen, - hash: ManagedBuffer::from_raw_handle(hash_handle.get_raw_handle()), - name: ManagedBuffer::from_raw_handle(name_handle.get_raw_handle()), - attributes: ManagedBuffer::from_raw_handle(attributes_handle.get_raw_handle()), - creator: ManagedAddress::from_raw_handle(creator_handle.get_raw_handle()), - royalties: BigUint::from_raw_handle(royalties_handle.get_raw_handle()), - uris: ManagedVec::from_raw_handle(uris_handle.get_raw_handle()), + unsafe { + EsdtTokenData { + token_type, + amount: BigUint::from_raw_handle(value_handle.get_raw_handle()), + frozen, + hash: ManagedBuffer::from_raw_handle(hash_handle.get_raw_handle()), + name: ManagedBuffer::from_raw_handle(name_handle.get_raw_handle()), + attributes: ManagedBuffer::from_raw_handle(attributes_handle.get_raw_handle()), + creator: ManagedAddress::from_raw_handle(creator_handle.get_raw_handle()), + royalties: BigUint::from_raw_handle(royalties_handle.get_raw_handle()), + uris: ManagedVec::from_raw_handle(uris_handle.get_raw_handle()), + } } } @@ -375,9 +400,13 @@ where call_value_handle.get_raw_handle(), ); - BackTransfers { - total_egld_amount: BigUint::from_raw_handle(call_value_handle.get_raw_handle()), - esdt_payments: ManagedVec::from_raw_handle(esdt_transfer_value_handle.get_raw_handle()), + unsafe { + BackTransfers { + total_egld_amount: BigUint::from_raw_handle(call_value_handle.get_raw_handle()), + esdt_payments: ManagedVec::from_raw_handle( + esdt_transfer_value_handle.get_raw_handle(), + ), + } } } @@ -441,13 +470,11 @@ where // load value A::storage_read_api_impl() .storage_load_managed_buffer_raw(temp_handle_1, temp_handle_2.clone()); - let result_handle: A::BigIntHandle = use_raw_handle(A::static_var_api_impl().next_handle()); // convert value to BigUint - A::managed_type_impl().mb_to_big_int_unsigned(temp_handle_2, result_handle.clone()); - - //wrap - BigUint::from_handle(result_handle) + let result = unsafe { BigUint::new_uninit() }; + A::managed_type_impl().mb_to_big_int_unsigned(temp_handle_2, result.get_handle()); + result } } diff --git a/framework/base/src/contract_base/wrappers/call_value_wrapper.rs b/framework/base/src/contract_base/wrappers/call_value_wrapper.rs index 3006805ef0..1edb635a9d 100644 --- a/framework/base/src/contract_base/wrappers/call_value_wrapper.rs +++ b/framework/base/src/contract_base/wrappers/call_value_wrapper.rs @@ -3,13 +3,13 @@ use core::marker::PhantomData; use crate::{ api::{ const_handles, use_raw_handle, CallValueApi, CallValueApiImpl, ErrorApi, ErrorApiImpl, - HandleConstraints, ManagedTypeApi, StaticVarApiImpl, + ManagedTypeApi, StaticVarApiFlags, StaticVarApiImpl, }, err_msg, types::{ BigUint, ConstDecimals, EgldOrEsdtTokenIdentifier, EgldOrEsdtTokenPayment, - EgldOrMultiEsdtPayment, EsdtTokenPayment, ManagedDecimal, ManagedRef, ManagedVec, - TokenIdentifier, + EgldOrMultiEsdtPayment, EsdtTokenPayment, ManagedDecimal, ManagedRef, ManagedType, + ManagedVec, ManagedVecRef, TokenIdentifier, }, }; @@ -34,11 +34,10 @@ where /// Retrieves the EGLD call value from the VM. /// Will return 0 in case of an ESDT transfer (cannot have both EGLD and ESDT transfer simultaneously). pub fn egld_value(&self) -> ManagedRef<'static, A, BigUint> { - let mut call_value_handle: A::BigIntHandle = - use_raw_handle(A::static_var_api_impl().get_call_value_egld_handle()); - if call_value_handle == const_handles::UNINITIALIZED_HANDLE { - call_value_handle = use_raw_handle(const_handles::CALL_VALUE_EGLD); - A::static_var_api_impl().set_call_value_egld_handle(call_value_handle.get_raw_handle()); + let call_value_handle: A::BigIntHandle = use_raw_handle(const_handles::CALL_VALUE_EGLD); + if !A::static_var_api_impl() + .flag_is_set_or_update(StaticVarApiFlags::CALL_VALUE_EGLD_INITIALIZED) + { A::call_value_api_impl().load_egld_value(call_value_handle.clone()); } unsafe { ManagedRef::wrap_handle(call_value_handle) } @@ -55,12 +54,11 @@ where /// Will return 0 results if nothing was transfered, or just EGLD. /// Fully managed underlying types, very efficient. pub fn all_esdt_transfers(&self) -> ManagedRef<'static, A, ManagedVec>> { - let mut call_value_handle: A::ManagedBufferHandle = - use_raw_handle(A::static_var_api_impl().get_call_value_multi_esdt_handle()); - if call_value_handle == const_handles::UNINITIALIZED_HANDLE { - call_value_handle = use_raw_handle(const_handles::CALL_VALUE_MULTI_ESDT); - A::static_var_api_impl() - .set_call_value_multi_esdt_handle(call_value_handle.get_raw_handle()); + let call_value_handle: A::ManagedBufferHandle = + use_raw_handle(const_handles::CALL_VALUE_MULTI_ESDT); + if !A::static_var_api_impl() + .flag_is_set_or_update(StaticVarApiFlags::CALL_VALUE_MULTI_ESDT_INITIALIZED) + { A::call_value_api_impl().load_all_esdt_transfers(call_value_handle.clone()); } unsafe { ManagedRef::wrap_handle(call_value_handle) } @@ -71,12 +69,12 @@ where /// Can be used to extract all payments in one line like this: /// /// `let [payment_a, payment_b, payment_c] = self.call_value().multi_esdt();`. - pub fn multi_esdt(&self) -> [EsdtTokenPayment; N] { - self.all_esdt_transfers() - .to_array_of_refs::() - .unwrap_or_else(|| { - A::error_api_impl().signal_error(err_msg::INCORRECT_NUM_ESDT_TRANSFERS.as_bytes()) - }) + pub fn multi_esdt(&self) -> [ManagedVecRef<'static, EsdtTokenPayment>; N] { + let esdt_transfers = self.all_esdt_transfers(); + let array = esdt_transfers.to_array_of_refs::().unwrap_or_else(|| { + A::error_api_impl().signal_error(err_msg::INCORRECT_NUM_ESDT_TRANSFERS.as_bytes()) + }); + unsafe { core::mem::transmute(array) } } /// Expects precisely one ESDT token transfer, fungible or not. @@ -84,9 +82,13 @@ where /// Will return the received ESDT payment. /// /// The amount cannot be 0, since that would not qualify as an ESDT transfer. - pub fn single_esdt(&self) -> EsdtTokenPayment { - let [payments] = self.multi_esdt(); - payments + pub fn single_esdt(&self) -> ManagedVecRef<'static, EsdtTokenPayment> { + let esdt_transfers = self.all_esdt_transfers(); + if esdt_transfers.len() != 1 { + A::error_api_impl().signal_error(err_msg::INCORRECT_NUM_ESDT_TRANSFERS.as_bytes()) + } + let value = esdt_transfers.get(0); + unsafe { core::mem::transmute(value) } } /// Expects precisely one fungible ESDT token transfer. @@ -94,12 +96,23 @@ where /// Returns the token ID and the amount for fungible ESDT transfers. /// /// The amount cannot be 0, since that would not qualify as an ESDT transfer. - pub fn single_fungible_esdt(&self) -> (TokenIdentifier, BigUint) { + pub fn single_fungible_esdt( + &self, + ) -> ( + ManagedRef<'static, A, TokenIdentifier>, + ManagedRef<'static, A, BigUint>, + ) { let payment = self.single_esdt(); if payment.token_nonce != 0 { A::error_api_impl().signal_error(err_msg::FUNGIBLE_TOKEN_EXPECTED_ERR_MSG.as_bytes()); } - (payment.token_identifier, payment.amount) + + unsafe { + ( + ManagedRef::wrap_handle(payment.token_identifier.get_handle()), + ManagedRef::wrap_handle(payment.amount.get_handle()), + ) + } } /// Accepts and returns either an EGLD payment, or a single ESDT token. @@ -115,7 +128,7 @@ where token_nonce: 0, amount: self.egld_value().clone_value(), }, - 1 => esdt_transfers.get(0).into(), + 1 => esdt_transfers.get(0).clone().into(), _ => A::error_api_impl().signal_error(err_msg::INCORRECT_NUM_ESDT_TRANSFERS.as_bytes()), } } diff --git a/framework/base/src/contract_base/wrappers/crypto_wrapper.rs b/framework/base/src/contract_base/wrappers/crypto_wrapper.rs index 369cca1a63..3731d4a964 100644 --- a/framework/base/src/contract_base/wrappers/crypto_wrapper.rs +++ b/framework/base/src/contract_base/wrappers/crypto_wrapper.rs @@ -1,10 +1,7 @@ use core::marker::PhantomData; use crate::{ - api::{ - use_raw_handle, CryptoApi, CryptoApiImpl, StaticVarApiImpl, KECCAK256_RESULT_LEN, - SHA256_RESULT_LEN, - }, + api::{CryptoApi, CryptoApiImpl, KECCAK256_RESULT_LEN, SHA256_RESULT_LEN}, types::{ManagedBuffer, ManagedByteArray, ManagedType, ManagedVec, MessageHashType}, }; @@ -30,30 +27,33 @@ where &self, data: B, ) -> ManagedByteArray { - let new_handle: A::ManagedBufferHandle = - use_raw_handle(A::static_var_api_impl().next_handle()); - A::crypto_api_impl().sha256_managed(new_handle.clone(), data.borrow().get_handle()); - ManagedByteArray::from_handle(new_handle) + unsafe { + let result = ManagedByteArray::new_uninit(); + A::crypto_api_impl().sha256_managed(result.get_handle(), data.borrow().get_handle()); + result + } } pub fn keccak256>>( &self, data: B, ) -> ManagedByteArray { - let new_handle: A::ManagedBufferHandle = - use_raw_handle(A::static_var_api_impl().next_handle()); - A::crypto_api_impl().keccak256_managed(new_handle.clone(), data.borrow().get_handle()); - ManagedByteArray::from_handle(new_handle) + unsafe { + let result = ManagedByteArray::new_uninit(); + A::crypto_api_impl().keccak256_managed(result.get_handle(), data.borrow().get_handle()); + result + } } pub fn ripemd160>>( &self, data: B, ) -> ManagedByteArray { - let new_handle: A::ManagedBufferHandle = - use_raw_handle(A::static_var_api_impl().next_handle()); - A::crypto_api_impl().ripemd160_managed(new_handle.clone(), data.borrow().get_handle()); - ManagedByteArray::from_handle(new_handle) + unsafe { + let result = ManagedByteArray::new_uninit(); + A::crypto_api_impl().ripemd160_managed(result.get_handle(), data.borrow().get_handle()); + result + } } pub fn verify_bls( @@ -122,14 +122,15 @@ where r: &ManagedBuffer, s: &ManagedBuffer, ) -> ManagedBuffer { - let new_handle: A::ManagedBufferHandle = - use_raw_handle(A::static_var_api_impl().next_handle()); - A::crypto_api_impl().encode_secp256k1_der_signature_managed( - r.get_handle(), - s.get_handle(), - new_handle.clone(), - ); - ManagedBuffer::from_handle(new_handle) + unsafe { + let result = ManagedBuffer::new_uninit(); + A::crypto_api_impl().encode_secp256k1_der_signature_managed( + r.get_handle(), + s.get_handle(), + result.get_handle(), + ); + result + } } /// Calls the Vm to verify secp256r1 signature. diff --git a/framework/base/src/contract_base/wrappers/send_raw_wrapper.rs b/framework/base/src/contract_base/wrappers/send_raw_wrapper.rs index 5d290369df..07466ac234 100644 --- a/framework/base/src/contract_base/wrappers/send_raw_wrapper.rs +++ b/framework/base/src/contract_base/wrappers/send_raw_wrapper.rs @@ -192,10 +192,12 @@ where new_address_handle, result_handle, ); - ( - ManagedAddress::from_raw_handle(new_address_handle), - ManagedVec::from_raw_handle(result_handle), - ) + unsafe { + ( + ManagedAddress::from_raw_handle(new_address_handle), + ManagedVec::from_raw_handle(result_handle), + ) + } } /// Deploys a new contract in the same shard by re-using the code of an already deployed source contract. @@ -222,10 +224,12 @@ where new_address_handle, result_handle, ); - ( - ManagedAddress::from_raw_handle(new_address_handle), - ManagedVec::from_raw_handle(result_handle), - ) + unsafe { + ( + ManagedAddress::from_raw_handle(new_address_handle), + ManagedVec::from_raw_handle(result_handle), + ) + } } pub fn upgrade_from_source_contract( @@ -291,7 +295,7 @@ where arg_buffer.get_handle().get_raw_handle(), result_handle, ); - ManagedVec::from_raw_handle(result_handle) + unsafe { ManagedVec::from_raw_handle(result_handle) } } pub fn execute_on_same_context_raw( @@ -311,7 +315,7 @@ where arg_buffer.get_handle().get_raw_handle(), result_handle, ); - ManagedVec::from_raw_handle(result_handle) + unsafe { ManagedVec::from_raw_handle(result_handle) } } /// Same shard, in-line execution of another contract. @@ -330,7 +334,7 @@ where arg_buffer.get_handle().get_raw_handle(), result_handle, ); - ManagedVec::from_raw_handle(result_handle) + unsafe { ManagedVec::from_raw_handle(result_handle) } } /// Allows synchronously calling a local function by name. Execution is resumed afterwards. @@ -357,8 +361,7 @@ where ); self.clean_return_data(); - - ManagedVec::from_raw_handle(result_handle) + unsafe { ManagedVec::from_raw_handle(result_handle) } } pub fn clean_return_data(&self) { diff --git a/framework/base/src/contract_base/wrappers/send_wrapper.rs b/framework/base/src/contract_base/wrappers/send_wrapper.rs index 3a11bde247..0c23b67cd4 100644 --- a/framework/base/src/contract_base/wrappers/send_wrapper.rs +++ b/framework/base/src/contract_base/wrappers/send_wrapper.rs @@ -2,6 +2,7 @@ use core::marker::PhantomData; use crate::codec::Empty; +use crate::types::ManagedRef; use crate::{ api::{BlockchainApi, CallTypeApi, StorageReadApi}, codec, @@ -589,7 +590,9 @@ where ) -> u64 { let big_zero = BigUint::zero(); let empty_buffer = ManagedBuffer::new(); - let empty_vec = ManagedVec::from_handle(empty_buffer.get_handle()); + + // sneakily reuses the same handle + let empty_vec = unsafe { ManagedRef::wrap_handle(empty_buffer.get_handle()) }; self.esdt_nft_create( 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 7417d6ca52..9fd49e115b 100644 --- a/framework/base/src/contract_base/wrappers/storage_raw_wrapper.rs +++ b/framework/base/src/contract_base/wrappers/storage_raw_wrapper.rs @@ -59,7 +59,8 @@ where V: TopDecode, { let key: StorageKey = storage_key.into(); - let result_buffer = ManagedBuffer::::from_handle(use_raw_handle(MBUF_TEMPORARY_1)); + let result_buffer = + unsafe { ManagedBuffer::::from_handle(use_raw_handle(MBUF_TEMPORARY_1)) }; A::storage_read_api_impl().storage_load_from_address( address.get_handle(), key.get_handle(), diff --git a/framework/base/src/hex_call_data/cd_de.rs b/framework/base/src/hex_call_data/cd_de.rs index ce6d6bdb63..f1826425e6 100644 --- a/framework/base/src/hex_call_data/cd_de.rs +++ b/framework/base/src/hex_call_data/cd_de.rs @@ -103,7 +103,7 @@ impl<'a> HexCallDataDeserializer<'a> { } } -impl<'a> TopDecodeMultiInput for HexCallDataDeserializer<'a> { +impl TopDecodeMultiInput for HexCallDataDeserializer<'_> { type ValueInput = Box<[u8]>; fn has_next(&self) -> bool { 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/arg_de_input.rs b/framework/base/src/io/arg_de_input.rs index 98faef2899..1b5502b6fa 100644 --- a/framework/base/src/io/arg_de_input.rs +++ b/framework/base/src/io/arg_de_input.rs @@ -1,10 +1,7 @@ use core::marker::PhantomData; use crate::{ - api::{ - use_raw_handle, EndpointArgumentApi, EndpointArgumentApiImpl, ManagedTypeApi, - StaticVarApiImpl, - }, + api::{EndpointArgumentApi, EndpointArgumentApiImpl, ManagedTypeApi}, codec::{ try_execute_then_cast, DecodeError, DecodeErrorHandler, TopDecodeInput, TryStaticCast, }, @@ -43,22 +40,30 @@ where } fn to_managed_buffer(&self) -> ManagedBuffer { - let mbuf_handle: AA::ManagedBufferHandle = - use_raw_handle(AA::static_var_api_impl().next_handle()); - AA::argument_api_impl().load_argument_managed_buffer(self.arg_index, mbuf_handle.clone()); - ManagedBuffer::from_handle(mbuf_handle) + unsafe { + let result = ManagedBuffer::new_uninit(); + AA::argument_api_impl() + .load_argument_managed_buffer(self.arg_index, result.get_handle()); + result + } } fn to_big_int(&self) -> BigInt { - let bi_handle: AA::BigIntHandle = use_raw_handle(AA::static_var_api_impl().next_handle()); - AA::argument_api_impl().load_argument_big_int_signed(self.arg_index, bi_handle.clone()); - BigInt::from_handle(bi_handle) + unsafe { + let result = BigInt::new_uninit(); + AA::argument_api_impl() + .load_argument_big_int_signed(self.arg_index, result.get_handle()); + result + } } fn to_big_uint(&self) -> BigUint { - let bi_handle: AA::BigIntHandle = use_raw_handle(AA::static_var_api_impl().next_handle()); - AA::argument_api_impl().load_argument_big_int_unsigned(self.arg_index, bi_handle.clone()); - BigUint::from_handle(bi_handle) + unsafe { + let result = BigUint::new_uninit(); + AA::argument_api_impl() + .load_argument_big_int_unsigned(self.arg_index, result.get_handle()); + result + } } } diff --git a/framework/base/src/io/arg_nested_tuple.rs b/framework/base/src/io/arg_nested_tuple.rs index fca34c9886..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,17 +194,16 @@ where N::next_multi_arg(loader, arg_names) } -fn callback_closure_args_loader() -> ManagedResultArgLoader +fn callback_closure_args_loader() -> ManagedVecRefIterator<'static, AA, ManagedBuffer> where AA: VMApi, { - AA::argument_api_impl() - .load_callback_closure_buffer(use_raw_handle(const_handles::MBUF_TEMPORARY_1)); - let cb_closure_args_serialized = - ManagedBuffer::::from_raw_handle(const_handles::MBUF_TEMPORARY_1); - let mut cb_closure_args_buffer = - ManagedArgBuffer::::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()) + let cb_closure_args_serialized = ManagedBuffer::::new(); + AA::argument_api_impl().load_callback_closure_buffer(cb_closure_args_serialized.get_handle()); + unsafe { + let mut cb_closure_args_buffer = + ManagedArgBuffer::::from_raw_handle(const_handles::CALLBACK_CLOSURE_ARGS_BUFFER); + cb_closure_args_buffer.deserialize_overwrite(cb_closure_args_serialized); + ManagedVecRefIterator::new_from_handle(cb_closure_args_buffer.forget_into_handle()) + } } 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 -where - A: ManagedTypeApi + ErrorApi, -{ - data: ManagedVec>, - data_len: usize, - next_index: usize, -} - -impl ManagedResultArgLoader -where - A: ManagedTypeApi + ErrorApi, -{ - pub fn new(data: ManagedVec>) -> Self { - let data_len = data.len(); - ManagedResultArgLoader { - data, - data_len, - next_index: 0, - } - } -} - -impl TopDecodeMultiInput for ManagedResultArgLoader -where - A: ManagedTypeApi + ErrorApi, -{ - type ValueInput = ManagedBuffer; - - fn has_next(&self) -> bool { - self.next_index < self.data_len - } - - fn next_value_input(&mut self, h: H) -> Result - 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/lib.rs b/framework/base/src/lib.rs index 9f6680af7c..b063a8d94a 100644 --- a/framework/base/src/lib.rs +++ b/framework/base/src/lib.rs @@ -1,6 +1,5 @@ #![no_std] #![allow(deprecated)] - pub use multiversx_sc_derive::{self as derive, contract, module, proxy}; // re-export basic heap types diff --git a/framework/base/src/storage/mappers/bi_di_mapper.rs b/framework/base/src/storage/mappers/bi_di_mapper.rs index ce0f24c159..decb892d2f 100644 --- a/framework/base/src/storage/mappers/bi_di_mapper.rs +++ b/framework/base/src/storage/mappers/bi_di_mapper.rs @@ -264,7 +264,7 @@ where } } -impl<'a, SA, K, V, A> Iterator for Iter<'a, SA, K, V, A> +impl Iterator for Iter<'_, SA, K, V, A> where SA: StorageMapperApi, A: StorageAddress, diff --git a/framework/base/src/storage/mappers/linked_list_mapper.rs b/framework/base/src/storage/mappers/linked_list_mapper.rs index a259467c29..0eba2da505 100644 --- a/framework/base/src/storage/mappers/linked_list_mapper.rs +++ b/framework/base/src/storage/mappers/linked_list_mapper.rs @@ -578,7 +578,7 @@ where } } -impl<'a, SA, T, A> Iterator for Iter<'a, SA, T, A> +impl Iterator for Iter<'_, SA, T, A> where SA: StorageMapperApi, A: StorageAddress, diff --git a/framework/base/src/storage/mappers/map_mapper.rs b/framework/base/src/storage/mappers/map_mapper.rs index 0da042334a..16cdf729fc 100644 --- a/framework/base/src/storage/mappers/map_mapper.rs +++ b/framework/base/src/storage/mappers/map_mapper.rs @@ -234,7 +234,7 @@ where } } -impl<'a, SA, A, K, V> Iterator for Iter<'a, SA, A, K, V> +impl Iterator for Iter<'_, SA, A, K, V> where SA: StorageMapperApi, A: StorageAddress, @@ -279,7 +279,7 @@ where } } -impl<'a, SA, A, K, V> Iterator for Values<'a, SA, A, K, V> +impl Iterator for Values<'_, SA, A, K, V> where SA: StorageMapperApi, A: StorageAddress, @@ -344,7 +344,7 @@ where pub(super) _marker: PhantomData<&'a mut (K, V)>, } -impl<'a, SA, A, K, V> Entry<'a, SA, A, K, V> +impl Entry<'_, SA, A, K, V> where SA: StorageMapperApi, A: StorageAddress, @@ -438,7 +438,7 @@ where } } -impl<'a, SA, A, K, V> VacantEntry<'a, SA, A, K, V> +impl VacantEntry<'_, SA, A, K, V> where SA: StorageMapperApi, A: StorageAddress, @@ -470,7 +470,7 @@ where } } -impl<'a, SA, A, K, V> OccupiedEntry<'a, SA, A, K, V> +impl OccupiedEntry<'_, SA, A, K, V> where SA: StorageMapperApi, A: StorageAddress, @@ -488,7 +488,7 @@ where } } -impl<'a, SA, K, V> OccupiedEntry<'a, SA, CurrentStorage, K, V> +impl OccupiedEntry<'_, SA, CurrentStorage, K, V> where SA: StorageMapperApi, K: TopEncode + TopDecode + NestedEncode + NestedDecode + Clone, diff --git a/framework/base/src/storage/mappers/map_storage_mapper.rs b/framework/base/src/storage/mappers/map_storage_mapper.rs index 699a3bab36..ed368a1822 100644 --- a/framework/base/src/storage/mappers/map_storage_mapper.rs +++ b/framework/base/src/storage/mappers/map_storage_mapper.rs @@ -221,7 +221,7 @@ where } } -impl<'a, SA, A, K, V> Iterator for Iter<'a, SA, A, K, V> +impl Iterator for Iter<'_, SA, A, K, V> where SA: StorageMapperApi, A: StorageAddress, @@ -268,7 +268,7 @@ where } } -impl<'a, SA, A, K, V> Iterator for Values<'a, SA, A, K, V> +impl Iterator for Values<'_, SA, A, K, V> where SA: StorageMapperApi, A: StorageAddress, @@ -388,7 +388,7 @@ where } } -impl<'a, SA, A, K, V> VacantEntry<'a, SA, A, K, V> +impl VacantEntry<'_, SA, A, K, V> where SA: StorageMapperApi, A: StorageAddress, @@ -420,7 +420,7 @@ where } } -impl<'a, SA, A, K, V> OccupiedEntry<'a, SA, A, K, V> +impl OccupiedEntry<'_, SA, A, K, V> where SA: StorageMapperApi, A: StorageAddress, @@ -438,7 +438,7 @@ where } } -impl<'a, SA, K, V> OccupiedEntry<'a, SA, CurrentStorage, K, V> +impl OccupiedEntry<'_, SA, CurrentStorage, K, V> where SA: StorageMapperApi, K: TopEncode + TopDecode + NestedEncode + NestedDecode + Clone + 'static, diff --git a/framework/base/src/storage/mappers/queue_mapper.rs b/framework/base/src/storage/mappers/queue_mapper.rs index 9937736b01..80572d1b41 100644 --- a/framework/base/src/storage/mappers/queue_mapper.rs +++ b/framework/base/src/storage/mappers/queue_mapper.rs @@ -484,7 +484,7 @@ where } } -impl<'a, SA, A, T> Iterator for Iter<'a, SA, A, T> +impl Iterator for Iter<'_, SA, A, T> where SA: StorageMapperApi, A: StorageAddress, diff --git a/framework/base/src/storage/mappers/unique_id_mapper.rs b/framework/base/src/storage/mappers/unique_id_mapper.rs index a1789d695a..a8605963a1 100644 --- a/framework/base/src/storage/mappers/unique_id_mapper.rs +++ b/framework/base/src/storage/mappers/unique_id_mapper.rs @@ -180,7 +180,7 @@ where } } -impl<'a, SA, A> Iterator for Iter<'a, SA, A> +impl Iterator for Iter<'_, SA, A> where SA: StorageMapperApi, A: StorageAddress, diff --git a/framework/base/src/storage/mappers/vec_mapper.rs b/framework/base/src/storage/mappers/vec_mapper.rs index 22b8763ece..0b7eb4cb5d 100644 --- a/framework/base/src/storage/mappers/vec_mapper.rs +++ b/framework/base/src/storage/mappers/vec_mapper.rs @@ -320,7 +320,7 @@ where } } -impl<'a, SA, T, A> Iterator for Iter<'a, SA, T, A> +impl Iterator for Iter<'_, SA, T, A> where SA: StorageMapperApi, A: StorageAddress, diff --git a/framework/base/src/storage/storage_get.rs b/framework/base/src/storage/storage_get.rs index 85107896dd..3cd6324aae 100644 --- a/framework/base/src/storage/storage_get.rs +++ b/framework/base/src/storage/storage_get.rs @@ -3,7 +3,7 @@ use core::{convert::Infallible, marker::PhantomData}; use crate::{ api::{ const_handles, use_raw_handle, ErrorApi, ErrorApiImpl, HandleConstraints, - ManagedBufferApiImpl, ManagedTypeApi, StaticVarApiImpl, StorageReadApi, StorageReadApiImpl, + ManagedBufferApiImpl, ManagedTypeApi, StorageReadApi, StorageReadApiImpl, }, codec::*, err_msg, @@ -33,11 +33,12 @@ where } fn to_managed_buffer(&self) -> ManagedBuffer { - let mbuf_handle: A::ManagedBufferHandle = - use_raw_handle(A::static_var_api_impl().next_handle()); - A::storage_read_api_impl() - .storage_load_managed_buffer_raw(self.key.buffer.get_handle(), mbuf_handle.clone()); - ManagedBuffer::from_handle(mbuf_handle) + unsafe { + let result = ManagedBuffer::new_uninit(); + A::storage_read_api_impl() + .storage_load_managed_buffer_raw(self.key.buffer.get_handle(), result.get_handle()); + result + } } fn to_big_uint(&self) -> BigUint { @@ -56,7 +57,7 @@ where } } -impl<'k, A> TopDecodeInput for StorageGetInput<'k, A> +impl TopDecodeInput for StorageGetInput<'_, A> where A: StorageReadApi + ManagedTypeApi + ErrorApi + 'static, { diff --git a/framework/base/src/storage/storage_get_from_address.rs b/framework/base/src/storage/storage_get_from_address.rs index 2b40987bd3..14b1bfabf0 100644 --- a/framework/base/src/storage/storage_get_from_address.rs +++ b/framework/base/src/storage/storage_get_from_address.rs @@ -1,7 +1,7 @@ use crate::{ api::{ const_handles, use_raw_handle, ErrorApi, HandleConstraints, ManagedBufferApiImpl, - ManagedTypeApi, StaticVarApiImpl, StorageReadApi, StorageReadApiImpl, + ManagedTypeApi, StorageReadApi, StorageReadApiImpl, }, codec::*, types::{ @@ -35,15 +35,15 @@ where } fn to_managed_buffer(&self) -> ManagedBuffer { - let mbuf_handle: A::ManagedBufferHandle = - use_raw_handle(A::static_var_api_impl().next_handle()); - A::storage_read_api_impl().storage_load_from_address( - self.addr.get_handle(), - self.key.buffer.get_handle(), - mbuf_handle.clone(), - ); - - ManagedBuffer::from_handle(mbuf_handle) + unsafe { + let result = ManagedBuffer::new_uninit(); + A::storage_read_api_impl().storage_load_from_address( + self.addr.get_handle(), + self.key.buffer.get_handle(), + result.get_handle(), + ); + result + } } fn to_big_uint(&self) -> BigUint { @@ -66,7 +66,7 @@ where } } -impl<'k, A> TopDecodeInput for StorageGetFromAddressInput<'k, A> +impl TopDecodeInput for StorageGetFromAddressInput<'_, A> where A: StorageReadApi + ManagedTypeApi + ErrorApi + 'static, { diff --git a/framework/base/src/storage/storage_key.rs b/framework/base/src/storage/storage_key.rs index b56358218b..74b4fa5171 100644 --- a/framework/base/src/storage/storage_key.rs +++ b/framework/base/src/storage/storage_key.rs @@ -22,7 +22,7 @@ where type OwnHandle = A::ManagedBufferHandle; #[inline] - fn from_handle(handle: A::ManagedBufferHandle) -> Self { + unsafe fn from_handle(handle: A::ManagedBufferHandle) -> Self { StorageKey { buffer: ManagedBuffer::from_handle(handle), } @@ -32,9 +32,17 @@ where self.buffer.get_handle() } + unsafe fn forget_into_handle(self) -> Self::OwnHandle { + self.buffer.forget_into_handle() + } + fn transmute_from_handle_ref(handle_ref: &A::ManagedBufferHandle) -> &Self { unsafe { core::mem::transmute(handle_ref) } } + + fn transmute_from_handle_ref_mut(handle_ref: &mut A::ManagedBufferHandle) -> &mut Self { + unsafe { core::mem::transmute(handle_ref) } + } } impl StorageKey diff --git a/framework/base/src/storage/storage_set.rs b/framework/base/src/storage/storage_set.rs index a2f3c3b722..8907b2abbf 100644 --- a/framework/base/src/storage/storage_set.rs +++ b/framework/base/src/storage/storage_set.rs @@ -37,7 +37,7 @@ where } } -impl<'k, A> TopEncodeOutput for StorageSetOutput<'k, A> +impl TopEncodeOutput for StorageSetOutput<'_, A> where A: StorageWriteApi + ManagedTypeApi + ErrorApi + 'static, { 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/annotated/annotated_impl_big_uint.rs b/framework/base/src/types/interaction/annotated/annotated_impl_big_uint.rs index f05952ab75..590e73545f 100644 --- a/framework/base/src/types/interaction/annotated/annotated_impl_big_uint.rs +++ b/framework/base/src/types/interaction/annotated/annotated_impl_big_uint.rs @@ -53,7 +53,7 @@ where } } -impl<'a, Env> AnnotatedValue> for ManagedRef<'a, Env::Api, BigUint> +impl AnnotatedValue> for ManagedRef<'_, Env::Api, BigUint> where Env: TxEnv, { 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 CallbackClosureForDeser { CallbackClosureMatcher::new(&self.callback_name) } - pub fn into_arg_loader(self) -> ManagedResultArgLoader { - ManagedResultArgLoader::new(self.closure_args.data) + pub fn arg_iter(&self) -> ManagedVecRefIterator<'_, M, ManagedBuffer> { + self.closure_args.iter_buffers() } } 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 -where - A: ManagedTypeApi + ErrorApi, -{ +#[derive(Clone, Copy, PartialEq, Eq)] +pub enum CallbackSelectorResult { Processed, - NotProcessed(CallbackClosureForDeser), + NotProcessed, +} + +impl CallbackSelectorResult { + pub fn is_processed(self) -> bool { + matches!(self, CallbackSelectorResult::Processed) + } } diff --git a/framework/base/src/types/interaction/contract_call_legacy/async_call_promises.rs b/framework/base/src/types/interaction/contract_call_legacy/async_call_promises.rs index ee3726c0eb..f2d091e2b3 100644 --- a/framework/base/src/types/interaction/contract_call_legacy/async_call_promises.rs +++ b/framework/base/src/types/interaction/contract_call_legacy/async_call_promises.rs @@ -1,5 +1,7 @@ +use core::ops::DerefMut; + use crate::{ - api::CallTypeApi, + api::{const_handles, CallTypeApi}, contract_base::SendRawWrapper, types::{BigUint, CallbackClosure, FunctionCall, ManagedAddress, ManagedBuffer}, }; @@ -41,16 +43,14 @@ where } pub fn register_promise(self) { - use crate::{api::const_handles, types::ManagedType}; - let mut cb_closure_args_serialized = - ManagedBuffer::::from_raw_handle(const_handles::MBUF_TEMPORARY_1); + unsafe { ManagedBuffer::temp_const_ref_mut(const_handles::MBUF_TEMPORARY_1) }; let callback_name; if let Some(callback_call) = self.callback_call { callback_name = callback_call.callback_name; callback_call .closure_args - .serialize_overwrite(&mut cb_closure_args_serialized); + .serialize_overwrite(cb_closure_args_serialized.deref_mut()); } else { callback_name = ""; cb_closure_args_serialized.overwrite(&[]); diff --git a/framework/base/src/types/interaction/contract_call_legacy/contract_call_convert.rs b/framework/base/src/types/interaction/contract_call_legacy/contract_call_convert.rs index fe4225d9a4..6a66c3e0f5 100644 --- a/framework/base/src/types/interaction/contract_call_legacy/contract_call_convert.rs +++ b/framework/base/src/types/interaction/contract_call_legacy/contract_call_convert.rs @@ -20,7 +20,7 @@ where ) -> Self { match payments.len() { 0 => self, - 1 => self.convert_to_single_transfer_esdt_call(payments.get(0)), + 1 => self.convert_to_single_transfer_esdt_call(payments.get(0).clone()), _ => self.convert_to_multi_transfer_esdt_call(payments), } } diff --git a/framework/base/src/types/interaction/contract_call_legacy/contract_call_exec.rs b/framework/base/src/types/interaction/contract_call_legacy/contract_call_exec.rs index 427218f1c8..e2281a4b38 100644 --- a/framework/base/src/types/interaction/contract_call_legacy/contract_call_exec.rs +++ b/framework/base/src/types/interaction/contract_call_legacy/contract_call_exec.rs @@ -36,10 +36,12 @@ where call_value_handle.get_raw_handle(), ); - ( - BigUint::from_raw_handle(call_value_handle.get_raw_handle()), - ManagedVec::from_raw_handle(esdt_transfer_value_handle.get_raw_handle()), - ) + unsafe { + ( + BigUint::from_raw_handle(call_value_handle.get_raw_handle()), + ManagedVec::from_raw_handle(esdt_transfer_value_handle.get_raw_handle()), + ) + } } pub fn to_call_data_string(&self) -> ManagedBuffer { @@ -206,7 +208,7 @@ where pub(super) fn transfer_execute_esdt(self, payments: ManagedVec>) { match payments.len() { 0 => self.transfer_execute_egld(BigUint::zero()), - 1 => self.transfer_execute_single_esdt(payments.get(0)), + 1 => self.transfer_execute_single_esdt(payments.get(0).clone()), _ => self.transfer_execute_multi_esdt(payments), } } 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, { - 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::::from(arg_id); RequestedResult::multi_decode_or_handle_err(&mut loader, h).unwrap_infallible() diff --git a/framework/base/src/types/interaction/expr/test_address.rs b/framework/base/src/types/interaction/expr/test_address.rs index 01d1dc819d..ed348c4e9c 100644 --- a/framework/base/src/types/interaction/expr/test_address.rs +++ b/framework/base/src/types/interaction/expr/test_address.rs @@ -56,13 +56,13 @@ impl<'a> TestAddress<'a> { } } -impl<'a, 'b> PartialEq> for TestAddress<'a> { +impl PartialEq> for TestAddress<'_> { fn eq(&self, other: &TestSCAddress) -> bool { self.to_address() == other.to_address() } } -impl<'a> PartialEq
for TestAddress<'a> { +impl PartialEq
for TestAddress<'_> { fn eq(&self, other: &Address) -> bool { &self.to_address() == other } @@ -74,7 +74,7 @@ impl<'a> PartialEq> for Address { } } -impl<'a, Api: ManagedTypeApi> PartialEq> for TestAddress<'a> { +impl PartialEq> for TestAddress<'_> { fn eq(&self, other: &ManagedAddress) -> bool { self.to_address() == other.to_address() } @@ -86,7 +86,7 @@ impl<'a, Api: ManagedTypeApi> PartialEq> for ManagedAddress } } -impl<'a, Env> AnnotatedValue> for TestAddress<'a> +impl AnnotatedValue> for TestAddress<'_> where Env: TxEnv, { @@ -102,7 +102,7 @@ where } } -impl<'a, Env> TxFrom for TestAddress<'a> +impl TxFrom for TestAddress<'_> where Env: TxEnv, { @@ -111,11 +111,11 @@ where expr.into() } } -impl<'a, Env> TxFromSpecified for TestAddress<'a> where Env: TxEnv {} -impl<'a, Env> TxTo for TestAddress<'a> where Env: TxEnv {} -impl<'a, Env> TxToSpecified for TestAddress<'a> where Env: TxEnv {} +impl TxFromSpecified for TestAddress<'_> where Env: TxEnv {} +impl TxTo for TestAddress<'_> where Env: TxEnv {} +impl TxToSpecified for TestAddress<'_> where Env: TxEnv {} -impl<'a> TopEncode for TestAddress<'a> { +impl TopEncode for TestAddress<'_> { fn top_encode_or_handle_err(&self, output: O, h: H) -> Result<(), H::HandledErr> where O: TopEncodeOutput, @@ -125,7 +125,7 @@ impl<'a> TopEncode for TestAddress<'a> { } } -impl<'a, Api> TypeAbiFrom> for ManagedAddress where Api: ManagedTypeApi {} +impl TypeAbiFrom> for ManagedAddress where Api: ManagedTypeApi {} #[cfg(test)] pub mod tests { diff --git a/framework/base/src/types/interaction/expr/test_sc_address.rs b/framework/base/src/types/interaction/expr/test_sc_address.rs index 564157fb94..520d3a6fc9 100644 --- a/framework/base/src/types/interaction/expr/test_sc_address.rs +++ b/framework/base/src/types/interaction/expr/test_sc_address.rs @@ -32,7 +32,7 @@ impl<'a> TestSCAddress<'a> { } } -impl<'a, Env> AnnotatedValue> for TestSCAddress<'a> +impl AnnotatedValue> for TestSCAddress<'_> where Env: TxEnv, { @@ -48,7 +48,7 @@ where } } -impl<'a> TestSCAddress<'a> { +impl TestSCAddress<'_> { pub fn to_address(&self) -> Address { self.eval_to_array().into() } @@ -58,13 +58,13 @@ impl<'a> TestSCAddress<'a> { } } -impl<'a, 'b> PartialEq> for TestSCAddress<'a> { +impl PartialEq> for TestSCAddress<'_> { fn eq(&self, other: &TestAddress) -> bool { self.to_address() == other.to_address() } } -impl<'a> PartialEq
for TestSCAddress<'a> { +impl PartialEq
for TestSCAddress<'_> { fn eq(&self, other: &Address) -> bool { &self.to_address() == other } @@ -76,7 +76,7 @@ impl<'a> PartialEq> for Address { } } -impl<'a, Api: ManagedTypeApi> PartialEq> for TestSCAddress<'a> { +impl PartialEq> for TestSCAddress<'_> { fn eq(&self, other: &ManagedAddress) -> bool { self.to_address() == other.to_address() } @@ -88,7 +88,7 @@ impl<'a, Api: ManagedTypeApi> PartialEq> for ManagedAddress TxFrom for TestSCAddress<'a> +impl TxFrom for TestSCAddress<'_> where Env: TxEnv, { @@ -97,11 +97,11 @@ where expr.into() } } -impl<'a, Env> TxFromSpecified for TestSCAddress<'a> where Env: TxEnv {} -impl<'a, Env> TxTo for TestSCAddress<'a> where Env: TxEnv {} -impl<'a, Env> TxToSpecified for TestSCAddress<'a> where Env: TxEnv {} +impl TxFromSpecified for TestSCAddress<'_> where Env: TxEnv {} +impl TxTo for TestSCAddress<'_> where Env: TxEnv {} +impl TxToSpecified for TestSCAddress<'_> where Env: TxEnv {} -impl<'a> TestSCAddress<'a> { +impl TestSCAddress<'_> { pub fn eval_to_array(&self) -> [u8; 32] { let result = *b"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00______________________"; let expr_bytes = self.name.as_bytes(); @@ -130,7 +130,7 @@ impl<'a> TestSCAddress<'a> { } } -impl<'a> TopEncode for TestSCAddress<'a> { +impl TopEncode for TestSCAddress<'_> { fn top_encode_or_handle_err(&self, output: O, h: H) -> Result<(), H::HandledErr> where O: TopEncodeOutput, @@ -140,7 +140,7 @@ impl<'a> TopEncode for TestSCAddress<'a> { } } -impl<'a, Api> TypeAbiFrom> for ManagedAddress where Api: ManagedTypeApi {} +impl TypeAbiFrom> for ManagedAddress where Api: ManagedTypeApi {} #[cfg(test)] pub mod tests { diff --git a/framework/base/src/types/interaction/expr/test_token_identifier.rs b/framework/base/src/types/interaction/expr/test_token_identifier.rs index 68865d8fbc..36ee135239 100644 --- a/framework/base/src/types/interaction/expr/test_token_identifier.rs +++ b/framework/base/src/types/interaction/expr/test_token_identifier.rs @@ -40,7 +40,7 @@ impl<'a> TestTokenIdentifier<'a> { } } -impl<'a, Env> AnnotatedValue> for TestTokenIdentifier<'a> +impl AnnotatedValue> for TestTokenIdentifier<'_> where Env: TxEnv, { @@ -64,7 +64,7 @@ where } } -impl<'a> TopEncode for TestTokenIdentifier<'a> { +impl TopEncode for TestTokenIdentifier<'_> { fn top_encode_or_handle_err(&self, output: O, h: H) -> Result<(), H::HandledErr> where O: TopEncodeOutput, @@ -74,5 +74,4 @@ impl<'a> TopEncode for TestTokenIdentifier<'a> { } } -impl<'a, Api> TypeAbiFrom> for TokenIdentifier where Api: ManagedTypeApi -{} +impl TypeAbiFrom> for TokenIdentifier where Api: ManagedTypeApi {} diff --git a/framework/base/src/types/interaction/managed_arg_buffer.rs b/framework/base/src/types/interaction/managed_arg_buffer.rs index c6dae76afd..fabe3f2c6d 100644 --- a/framework/base/src/types/interaction/managed_arg_buffer.rs +++ b/framework/base/src/types/interaction/managed_arg_buffer.rs @@ -33,7 +33,7 @@ where type OwnHandle = M::ManagedBufferHandle; #[inline] - fn from_handle(handle: M::ManagedBufferHandle) -> Self { + unsafe fn from_handle(handle: M::ManagedBufferHandle) -> Self { ManagedArgBuffer { data: ManagedVec::from_handle(handle), } @@ -43,9 +43,17 @@ where self.data.get_handle() } + unsafe fn forget_into_handle(self) -> Self::OwnHandle { + self.data.forget_into_handle() + } + fn transmute_from_handle_ref(handle_ref: &M::ManagedBufferHandle) -> &Self { unsafe { core::mem::transmute(handle_ref) } } + + fn transmute_from_handle_ref_mut(handle_ref: &mut M::ManagedBufferHandle) -> &mut Self { + unsafe { core::mem::transmute(handle_ref) } + } } impl ManagedArgBuffer @@ -160,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/interaction/markers/to_caller.rs b/framework/base/src/types/interaction/markers/to_caller.rs index f24191ce9f..9066a16239 100644 --- a/framework/base/src/types/interaction/markers/to_caller.rs +++ b/framework/base/src/types/interaction/markers/to_caller.rs @@ -1,5 +1,5 @@ use crate::{ - api::{const_handles, use_raw_handle, BlockchainApi, BlockchainApiImpl, CallTypeApi}, + api::{const_handles, BlockchainApi, BlockchainApiImpl, CallTypeApi}, contract_base::BlockchainWrapper, types::{ AnnotatedValue, ManagedAddress, ManagedBuffer, ManagedType, TxScEnv, TxTo, TxToSpecified, @@ -25,9 +25,11 @@ where where F: FnOnce(&ManagedAddress) -> R, { - let caller_handle: Api::ManagedBufferHandle = use_raw_handle(const_handles::ADDRESS_CALLER); - Api::blockchain_api_impl().load_caller_managed(caller_handle.clone()); - f(&ManagedAddress::from_handle(caller_handle)) + unsafe { + let temp = ManagedAddress::temp_const_ref(const_handles::ADDRESS_CALLER); + Api::blockchain_api_impl().load_caller_managed(temp.get_handle()); + f(&temp) + } } } diff --git a/framework/base/src/types/interaction/markers/to_self.rs b/framework/base/src/types/interaction/markers/to_self.rs index f339a448e2..8a78e13d6d 100644 --- a/framework/base/src/types/interaction/markers/to_self.rs +++ b/framework/base/src/types/interaction/markers/to_self.rs @@ -1,5 +1,5 @@ use crate::{ - api::{const_handles, use_raw_handle, BlockchainApi, BlockchainApiImpl, CallTypeApi}, + api::{const_handles, BlockchainApi, BlockchainApiImpl, CallTypeApi}, contract_base::BlockchainWrapper, types::{ AnnotatedValue, ManagedAddress, ManagedBuffer, ManagedType, TxScEnv, TxTo, TxToSpecified, @@ -26,10 +26,11 @@ where where F: FnOnce(&ManagedAddress) -> R, { - let sc_address_handle: Api::ManagedBufferHandle = - use_raw_handle(const_handles::ADDRESS_CALLER); - Api::blockchain_api_impl().load_sc_address_managed(sc_address_handle.clone()); - f(&ManagedAddress::from_handle(sc_address_handle)) + unsafe { + let temp = ManagedAddress::temp_const_ref(const_handles::ADDRESS_CALLER); + Api::blockchain_api_impl().load_sc_address_managed(temp.get_handle()); + f(&temp) + } } } diff --git a/framework/base/src/types/interaction/result_handlers/returns_bt_single_esdt.rs b/framework/base/src/types/interaction/result_handlers/returns_bt_single_esdt.rs index 996891c1c2..10a4c59003 100644 --- a/framework/base/src/types/interaction/result_handlers/returns_bt_single_esdt.rs +++ b/framework/base/src/types/interaction/result_handlers/returns_bt_single_esdt.rs @@ -28,6 +28,7 @@ where Env::Api::error_api_impl().signal_error(b"Back transfers expected to be a single ESDT") } - esdt_payments.get(0) + let x = esdt_payments.get(0).clone(); + x } } 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 = ArgErrorHandler::::from(arg_id); RequestedResult::multi_decode_or_handle_err(&mut loader, h).unwrap_infallible() diff --git a/framework/base/src/types/interaction/tx_exec/tx_exec_async_promises.rs b/framework/base/src/types/interaction/tx_exec/tx_exec_async_promises.rs index 38e38fcbcd..333bbf9379 100644 --- a/framework/base/src/types/interaction/tx_exec/tx_exec_async_promises.rs +++ b/framework/base/src/types/interaction/tx_exec/tx_exec_async_promises.rs @@ -3,8 +3,8 @@ use crate::{ contract_base::{ErrorHelper, SendRawWrapper}, types::{ interaction::callback_closure::CallbackClosureWithGas, CallbackClosure, ExplicitGas, - FunctionCall, ManagedBuffer, ManagedType, OriginalResultMarker, Tx, TxGas, TxGasValue, - TxPayment, TxResultHandler, TxScEnv, TxToSpecified, + FunctionCall, ManagedBuffer, OriginalResultMarker, Tx, TxGas, TxGasValue, TxPayment, + TxResultHandler, TxScEnv, TxToSpecified, }, }; @@ -160,7 +160,7 @@ where pub fn register_promise(self) { let callback_name = self.result_handler.callback_name(); let mut cb_closure_args_serialized = - ManagedBuffer::::from_raw_handle(const_handles::MBUF_TEMPORARY_1); + unsafe { ManagedBuffer::temp_const_ref_mut(const_handles::MBUF_TEMPORARY_1) }; self.result_handler .overwrite_with_serialized_args(&mut cb_closure_args_serialized); let extra_gas_for_callback = self.result_handler.gas_for_callback(); diff --git a/framework/base/src/types/interaction/tx_payment/test_esdt_transfer.rs b/framework/base/src/types/interaction/tx_payment/test_esdt_transfer.rs index 99d00a219e..307bc06133 100644 --- a/framework/base/src/types/interaction/tx_payment/test_esdt_transfer.rs +++ b/framework/base/src/types/interaction/tx_payment/test_esdt_transfer.rs @@ -26,7 +26,7 @@ where } } -impl<'a, Env> TxPayment for TestEsdtTransfer<'a> +impl TxPayment for TestEsdtTransfer<'_> where Env: TxEnv, { diff --git a/framework/base/src/types/interaction/tx_payment/tx_payment_egld_or_esdt_refs.rs b/framework/base/src/types/interaction/tx_payment/tx_payment_egld_or_esdt_refs.rs index 14f9058b55..1326974817 100644 --- a/framework/base/src/types/interaction/tx_payment/tx_payment_egld_or_esdt_refs.rs +++ b/framework/base/src/types/interaction/tx_payment/tx_payment_egld_or_esdt_refs.rs @@ -2,7 +2,7 @@ use crate::types::{BigUint, EgldOrEsdtTokenPaymentRefs, ManagedAddress, TxFrom, use super::{Egld, FullPaymentData, FunctionCall, TxEnv, TxPayment}; -impl<'a, Env> TxPayment for EgldOrEsdtTokenPaymentRefs<'a, Env::Api> +impl TxPayment for EgldOrEsdtTokenPaymentRefs<'_, Env::Api> where Env: TxEnv, { diff --git a/framework/base/src/types/interaction/tx_payment/tx_payment_egld_or_multi_esdt_ref.rs b/framework/base/src/types/interaction/tx_payment/tx_payment_egld_or_multi_esdt_ref.rs index 9d4eb6c20a..8cd88504ae 100644 --- a/framework/base/src/types/interaction/tx_payment/tx_payment_egld_or_multi_esdt_ref.rs +++ b/framework/base/src/types/interaction/tx_payment/tx_payment_egld_or_multi_esdt_ref.rs @@ -2,7 +2,7 @@ use crate::types::{BigUint, EgldOrMultiEsdtPaymentRefs, ManagedAddress, TxFrom, use super::{Egld, FullPaymentData, FunctionCall, TxEnv, TxPayment}; -impl<'a, Env> TxPayment for EgldOrMultiEsdtPaymentRefs<'a, Env::Api> +impl TxPayment for EgldOrMultiEsdtPaymentRefs<'_, Env::Api> where Env: TxEnv, { diff --git a/framework/base/src/types/interaction/tx_payment/tx_payment_egld_value.rs b/framework/base/src/types/interaction/tx_payment/tx_payment_egld_value.rs index 99d91b618f..9b32d93a4e 100644 --- a/framework/base/src/types/interaction/tx_payment/tx_payment_egld_value.rs +++ b/framework/base/src/types/interaction/tx_payment/tx_payment_egld_value.rs @@ -10,5 +10,5 @@ where impl TxEgldValue for BigUint where Env: TxEnv {} impl TxEgldValue for &BigUint where Env: TxEnv {} -impl<'a, Env> TxEgldValue for ManagedRef<'a, Env::Api, BigUint> where Env: TxEnv {} +impl TxEgldValue for ManagedRef<'_, Env::Api, BigUint> where Env: TxEnv {} impl TxEgldValue for u64 where Env: TxEnv {} diff --git a/framework/base/src/types/interaction/tx_payment/tx_payment_multi_esdt.rs b/framework/base/src/types/interaction/tx_payment/tx_payment_multi_esdt.rs index c0afc2055c..ab030362d2 100644 --- a/framework/base/src/types/interaction/tx_payment/tx_payment_multi_esdt.rs +++ b/framework/base/src/types/interaction/tx_payment/tx_payment_multi_esdt.rs @@ -16,7 +16,7 @@ where impl TxPaymentMultiEsdt for MultiEsdtPayment where Env: TxEnv {} impl TxPaymentMultiEsdt for &MultiEsdtPayment where Env: TxEnv {} -impl<'a, Env> TxPaymentMultiEsdt for ManagedRef<'a, Env::Api, MultiEsdtPayment> where +impl TxPaymentMultiEsdt for ManagedRef<'_, Env::Api, MultiEsdtPayment> where Env: TxEnv { } @@ -76,7 +76,7 @@ where } } -impl<'a, Env> TxPayment for ManagedRef<'a, Env::Api, MultiEsdtPayment> +impl TxPayment for ManagedRef<'_, Env::Api, MultiEsdtPayment> where Env: TxEnv, { diff --git a/framework/base/src/types/interaction/tx_payment/tx_payment_single_esdt_ref.rs b/framework/base/src/types/interaction/tx_payment/tx_payment_single_esdt_ref.rs index c91391d316..6aecb277a6 100644 --- a/framework/base/src/types/interaction/tx_payment/tx_payment_single_esdt_ref.rs +++ b/framework/base/src/types/interaction/tx_payment/tx_payment_single_esdt_ref.rs @@ -7,7 +7,7 @@ use crate::{ use super::{FullPaymentData, FunctionCall, TxEnv, TxPayment}; -impl<'a, Env> TxPayment for EsdtTokenPaymentRefs<'a, Env::Api> +impl TxPayment for EsdtTokenPaymentRefs<'_, Env::Api> where Env: TxEnv, { diff --git a/framework/base/src/types/io/mod.rs b/framework/base/src/types/io.rs similarity index 100% rename from framework/base/src/types/io/mod.rs rename to framework/base/src/types/io.rs diff --git a/framework/base/src/types/managed/mod.rs b/framework/base/src/types/managed.rs similarity index 100% rename from framework/base/src/types/managed/mod.rs rename to framework/base/src/types/managed.rs diff --git a/framework/base/src/types/managed/basic/big_float.rs b/framework/base/src/types/managed/basic/big_float.rs index 54850a1672..9306769130 100644 --- a/framework/base/src/types/managed/basic/big_float.rs +++ b/framework/base/src/types/managed/basic/big_float.rs @@ -27,7 +27,7 @@ pub struct BigFloat { impl ManagedType for BigFloat { type OwnHandle = M::BigFloatHandle; - fn from_handle(handle: M::BigFloatHandle) -> Self { + unsafe fn from_handle(handle: M::BigFloatHandle) -> Self { BigFloat { handle } } @@ -35,9 +35,21 @@ impl ManagedType for BigFloat { self.handle.clone() } + unsafe fn forget_into_handle(self) -> Self::OwnHandle { + unsafe { + let handle = core::ptr::read(&self.handle); + core::mem::forget(self); + handle + } + } + fn transmute_from_handle_ref(handle_ref: &M::BigFloatHandle) -> &Self { unsafe { core::mem::transmute(handle_ref) } } + + fn transmute_from_handle_ref_mut(handle_ref: &mut M::BigFloatHandle) -> &mut Self { + unsafe { core::mem::transmute(handle_ref) } + } } impl From<&ManagedBuffer> for BigFloat { @@ -81,10 +93,11 @@ macro_rules! big_float_conv_num { impl From<$num_ty> for BigFloat { #[inline] fn from(value: $num_ty) -> Self { - let new_bf_handle: M::BigFloatHandle = - use_raw_handle(M::static_var_api_impl().next_handle()); - M::managed_type_impl().bf_set_i64(new_bf_handle.clone(), value as i64); - BigFloat::from_handle(new_bf_handle) + unsafe { + let result = BigFloat::new_uninit(); + M::managed_type_impl().bf_set_i64(result.get_handle(), value as i64); + result + } } } }; @@ -98,31 +111,31 @@ big_float_conv_num! {i8} impl BigFloat { pub fn neg(&self) -> Self { - let new_bf_handle: M::BigFloatHandle = - use_raw_handle(M::static_var_api_impl().next_handle()); - M::managed_type_impl().bf_neg(new_bf_handle.clone(), self.handle.clone()); - BigFloat::from_handle(new_bf_handle) + unsafe { + let result = BigFloat::new_uninit(); + M::managed_type_impl().bf_neg(result.get_handle(), self.handle.clone()); + result + } } pub fn abs(&self) -> Self { - let new_bf_handle: M::BigFloatHandle = - use_raw_handle(M::static_var_api_impl().next_handle()); - M::managed_type_impl().bf_abs(new_bf_handle.clone(), self.handle.clone()); - BigFloat::from_handle(new_bf_handle) + unsafe { + let result = BigFloat::new_uninit(); + M::managed_type_impl().bf_abs(result.get_handle(), self.handle.clone()); + result + } } - pub fn from_big_uint(big_uint: &BigUint) -> Self { - let new_bf_handle: M::BigFloatHandle = - use_raw_handle(M::static_var_api_impl().next_handle()); - M::managed_type_impl().bf_set_bi(new_bf_handle.clone(), big_uint.value.handle.clone()); - BigFloat::from_handle(new_bf_handle) + pub fn from_big_int(big_int: &BigInt) -> Self { + unsafe { + let result = BigFloat::new_uninit(); + M::managed_type_impl().bf_set_bi(result.get_handle(), big_int.handle.clone()); + result + } } - pub fn from_big_int(big_int: &BigInt) -> Self { - let new_bf_handle: M::BigFloatHandle = - use_raw_handle(M::static_var_api_impl().next_handle()); - M::managed_type_impl().bf_set_bi(new_bf_handle.clone(), big_int.handle.clone()); - BigFloat::from_handle(new_bf_handle) + pub fn from_big_uint(big_uint: &BigUint) -> Self { + Self::from_big_int(big_uint.as_big_int()) } #[inline] @@ -134,42 +147,45 @@ impl BigFloat { let api = M::managed_type_impl(); let new_bf_handle = api.bf_from_parts(integral_part_value, fractional_part_value, exponent_value); - BigFloat::from_handle(new_bf_handle) + unsafe { BigFloat::from_handle(new_bf_handle) } } #[inline] pub fn from_frac(numerator_value: i64, denominator_value: i64) -> Self { let api = M::managed_type_impl(); let new_bf_handle = api.bf_from_frac(numerator_value, denominator_value); - BigFloat::from_handle(new_bf_handle) + unsafe { BigFloat::from_handle(new_bf_handle) } } #[inline] pub fn from_sci(significand_value: i64, exponent_value: i32) -> Self { let api = M::managed_type_impl(); let new_bf_handle = api.bf_from_sci(significand_value, exponent_value as i64); - BigFloat::from_handle(new_bf_handle) + unsafe { BigFloat::from_handle(new_bf_handle) } } pub fn trunc(&self) -> BigInt { - let result: M::BigIntHandle = use_raw_handle(M::static_var_api_impl().next_handle()); - let api = M::managed_type_impl(); - api.bf_trunc(result.clone(), self.handle.clone()); - BigInt::from_handle(result) + unsafe { + let result = BigInt::new_uninit(); + M::managed_type_impl().bf_trunc(result.get_handle(), self.handle.clone()); + result + } } pub fn floor(&self) -> BigInt { - let result: M::BigIntHandle = use_raw_handle(M::static_var_api_impl().next_handle()); - let api = M::managed_type_impl(); - api.bf_floor(result.clone(), self.handle.clone()); - BigInt::from_handle(result) + unsafe { + let result = BigInt::new_uninit(); + M::managed_type_impl().bf_floor(result.get_handle(), self.handle.clone()); + result + } } pub fn ceil(&self) -> BigInt { - let result: M::BigIntHandle = use_raw_handle(M::static_var_api_impl().next_handle()); - let api = M::managed_type_impl(); - api.bf_ceil(result.clone(), self.handle.clone()); - BigInt::from_handle(result) + unsafe { + let result = BigInt::new_uninit(); + M::managed_type_impl().bf_ceil(result.get_handle(), self.handle.clone()); + result + } } pub fn to_fixed_point(&self, denominator: &BigFloat) -> BigInt { @@ -250,38 +266,52 @@ impl BigFloat { #[inline] pub fn zero() -> Self { - BigFloat::from_handle(M::managed_type_impl().bf_new_zero()) + unsafe { BigFloat::from_handle(M::managed_type_impl().bf_new_zero()) } } pub fn from_buffer(managed_buffer: &ManagedBuffer) -> Self { - let new_bf_handle: M::BigFloatHandle = - use_raw_handle(M::static_var_api_impl().next_handle()); - M::managed_type_impl() - .mb_to_big_float(managed_buffer.handle.clone(), new_bf_handle.clone()); - BigFloat::from_handle(new_bf_handle) + unsafe { + let result = BigFloat::new_uninit(); + M::managed_type_impl() + .mb_to_big_float(managed_buffer.handle.clone(), result.get_handle()); + result + } } pub fn to_buffer(&self) -> ManagedBuffer { - let new_man_buf_handle: M::ManagedBufferHandle = - use_raw_handle(M::static_var_api_impl().next_handle()); - M::managed_type_impl().mb_from_big_float(self.handle.clone(), new_man_buf_handle.clone()); - ManagedBuffer::from_handle(new_man_buf_handle) + unsafe { + let result = ManagedBuffer::new_uninit(); + M::managed_type_impl().mb_from_big_float(self.get_handle(), result.get_handle()); + result + } + } + + /// Creates a new object, without initializing it. + /// + /// ## Safety + /// + /// The value needs to be initialized after creation, otherwise the VM will halt the first time the value is attempted to be read. + pub unsafe fn new_uninit() -> Self { + let new_handle: M::BigFloatHandle = use_raw_handle(M::static_var_api_impl().next_handle()); + BigFloat::from_handle(new_handle) } } impl BigFloat { pub fn sqrt(&self) -> Self { - let api = M::managed_type_impl(); - let new_handle: M::BigFloatHandle = use_raw_handle(M::static_var_api_impl().next_handle()); - api.bf_sqrt(new_handle.clone(), self.handle.clone()); - BigFloat::from_handle(new_handle) + unsafe { + let result = BigFloat::new_uninit(); + M::managed_type_impl().bf_sqrt(result.get_handle(), self.handle.clone()); + result + } } pub fn pow(&self, exp: i32) -> Self { - let api = M::managed_type_impl(); - let new_handle: M::BigFloatHandle = use_raw_handle(M::static_var_api_impl().next_handle()); - api.bf_pow(new_handle.clone(), self.handle.clone(), exp); - BigFloat::from_handle(new_handle) + unsafe { + let result = BigFloat::new_uninit(); + M::managed_type_impl().bf_pow(result.get_handle(), self.handle.clone(), exp); + result + } } /// Returns the sign of the `BigFloat` as a `Sign`. @@ -295,9 +325,11 @@ impl BigFloat { /// Returns the magnitude of the `BigFloat` pub fn magnitude(&self) -> BigFloat { - let result: M::BigFloatHandle = use_raw_handle(M::static_var_api_impl().next_handle()); - M::managed_type_impl().bf_abs(result.clone(), self.handle.clone()); - BigFloat::from_handle(result) + unsafe { + let result = BigFloat::new_uninit(); + M::managed_type_impl().bf_abs(result.get_handle(), self.handle.clone()); + result + } } /// Convert this `BigFloat` into its `Sign` and its magnitude, @@ -337,9 +369,11 @@ impl BigFloat { impl Clone for BigFloat { fn clone(&self) -> Self { - let new_handle: M::BigFloatHandle = use_raw_handle(M::static_var_api_impl().next_handle()); - M::managed_type_impl().bf_clone(new_handle.clone(), self.handle.clone()); - BigFloat::from_handle(new_handle) + unsafe { + let result = BigFloat::new_uninit(); + M::managed_type_impl().bf_clone(result.get_handle(), self.handle.clone()); + result + } } } diff --git a/framework/base/src/types/managed/basic/big_float_operators.rs b/framework/base/src/types/managed/basic/big_float_operators.rs index 7874c1ab86..e8d27016a8 100644 --- a/framework/base/src/types/managed/basic/big_float_operators.rs +++ b/framework/base/src/types/managed/basic/big_float_operators.rs @@ -1,6 +1,6 @@ use super::BigFloat; use crate::{ - api::{use_raw_handle, BigFloatApiImpl, ManagedTypeApi, StaticVarApiImpl}, + api::{BigFloatApiImpl, ManagedTypeApi}, types::managed::managed_type_trait::ManagedType, }; use core::ops::{Add, AddAssign, Div, DivAssign, Mul, MulAssign, Neg, Sub, SubAssign}; @@ -16,7 +16,7 @@ macro_rules! binary_operator { self.handle.clone(), other.handle.clone(), ); - BigFloat::from_handle(self.handle.clone()) + self } } @@ -24,14 +24,15 @@ macro_rules! binary_operator { type Output = BigFloat; fn $method(self, other: &BigFloat) -> BigFloat { - let result_handle: M::BigFloatHandle = - use_raw_handle(M::static_var_api_impl().next_handle()); - M::managed_type_impl().$api_func( - result_handle.clone(), - self.handle.clone(), - other.handle.clone(), - ); - BigFloat::from_handle(result_handle) + unsafe { + let result = BigFloat::new_uninit(); + M::managed_type_impl().$api_func( + result.get_handle(), + self.handle.clone(), + other.handle.clone(), + ); + result + } } } }; @@ -79,9 +80,10 @@ impl Neg for BigFloat { type Output = BigFloat; fn neg(self) -> Self::Output { - let result_handle: M::BigFloatHandle = - use_raw_handle(M::static_var_api_impl().next_handle()); - M::managed_type_impl().bf_neg(result_handle.clone(), self.handle); - BigFloat::from_handle(result_handle) + unsafe { + let result = BigFloat::new_uninit(); + M::managed_type_impl().bf_neg(result.get_handle(), self.handle.clone()); + result + } } } diff --git a/framework/base/src/types/managed/basic/big_int.rs b/framework/base/src/types/managed/basic/big_int.rs index c705511f56..464bc4150c 100644 --- a/framework/base/src/types/managed/basic/big_int.rs +++ b/framework/base/src/types/managed/basic/big_int.rs @@ -11,7 +11,9 @@ use crate::{ NestedEncodeOutput, TopDecode, TopDecodeInput, TopEncode, TopEncodeOutput, TryStaticCast, }, formatter::{hex_util::encode_bytes_as_hex, FormatByteReceiver, SCDisplay}, - types::{heap::BoxedBytes, BigUint, ManagedBuffer, ManagedOption, ManagedType, Sign}, + types::{ + heap::BoxedBytes, BigUint, ManagedBuffer, ManagedOption, ManagedRef, ManagedType, Sign, + }, }; use super::cast_to_i64::cast_to_i64; @@ -25,7 +27,7 @@ pub struct BigInt { impl ManagedType for BigInt { type OwnHandle = M::BigIntHandle; - fn from_handle(handle: M::BigIntHandle) -> Self { + unsafe fn from_handle(handle: M::BigIntHandle) -> Self { BigInt { handle, _phantom: PhantomData, @@ -36,9 +38,21 @@ impl ManagedType for BigInt { self.handle.clone() } + unsafe fn forget_into_handle(self) -> Self::OwnHandle { + unsafe { + let handle = core::ptr::read(&self.handle); + core::mem::forget(self); + handle + } + } + fn transmute_from_handle_ref(handle_ref: &M::BigIntHandle) -> &Self { unsafe { core::mem::transmute(handle_ref) } } + + fn transmute_from_handle_ref_mut(handle_ref: &mut M::BigIntHandle) -> &mut Self { + unsafe { core::mem::transmute(handle_ref) } + } } impl Default for BigInt { @@ -63,6 +77,16 @@ impl From> for BigInt { } impl BigInt { + /// Creates a new object, without initializing it. + /// + /// ## Safety + /// + /// The value needs to be initialized after creation, otherwise the VM will halt the first time the value is attempted to be read. + pub unsafe fn new_uninit() -> Self { + let new_handle: M::BigIntHandle = use_raw_handle(M::static_var_api_impl().next_handle()); + BigInt::from_handle(new_handle) + } + pub(crate) fn set_value(handle: M::BigIntHandle, value: T) where T: TryInto, @@ -83,7 +107,7 @@ impl BigInt { impl From> for BigInt { #[inline] fn from(item: BigUint) -> Self { - BigInt::from_handle(item.get_handle()) + item.into_big_int() } } @@ -92,10 +116,11 @@ macro_rules! big_int_conv_num { impl From<$num_ty> for BigInt { #[inline] fn from(value: $num_ty) -> Self { - let handle: M::BigIntHandle = - use_raw_handle(M::static_var_api_impl().next_handle()); - Self::set_value(handle.clone(), value); - BigInt::from_handle(handle) + unsafe { + let result = BigInt::new_uninit(); + Self::set_value(result.get_handle(), value); + result + } } } @@ -151,10 +176,11 @@ impl From for BigInt { impl BigInt { #[inline] pub fn zero() -> Self { - let handle: M::BigIntHandle = use_raw_handle(M::static_var_api_impl().next_handle()); - // TODO: seting 0 will no longer be needed once we fix VM handle error - M::managed_type_impl().bi_set_int64(handle.clone(), 0); - BigInt::from_handle(handle) + unsafe { + let result = BigInt::new_uninit(); + M::managed_type_impl().bi_set_int64(result.get_handle(), 0); + result + } } #[inline] @@ -171,9 +197,11 @@ impl BigInt { pub fn from_signed_bytes_be(bytes: &[u8]) -> Self { let mb_handle: M::ManagedBufferHandle = use_raw_handle(const_handles::MBUF_TEMPORARY_1); M::managed_type_impl().mb_overwrite(mb_handle.clone(), bytes); - let handle: M::BigIntHandle = use_raw_handle(M::static_var_api_impl().next_handle()); - M::managed_type_impl().mb_to_big_int_signed(mb_handle, handle.clone()); - BigInt::from_handle(handle) + unsafe { + let result = BigInt::new_uninit(); + M::managed_type_impl().mb_to_big_int_signed(mb_handle, result.get_handle()); + result + } } #[inline] @@ -185,41 +213,47 @@ impl BigInt { #[inline] pub fn from_signed_bytes_be_buffer(managed_buffer: &ManagedBuffer) -> Self { - let handle: M::BigIntHandle = use_raw_handle(M::static_var_api_impl().next_handle()); - M::managed_type_impl().mb_to_big_int_signed(managed_buffer.handle.clone(), handle.clone()); - BigInt::from_handle(handle) + unsafe { + let result = BigInt::new_uninit(); + M::managed_type_impl() + .mb_to_big_int_signed(managed_buffer.handle.clone(), result.get_handle()); + result + } } #[inline] pub fn to_signed_bytes_be_buffer(&self) -> ManagedBuffer { - let mb_handle: M::ManagedBufferHandle = - use_raw_handle(M::static_var_api_impl().next_handle()); - M::managed_type_impl().mb_from_big_int_signed(self.handle.clone(), mb_handle.clone()); - ManagedBuffer::from_handle(mb_handle) + unsafe { + let result = ManagedBuffer::new_uninit(); + M::managed_type_impl().mb_from_big_int_signed(self.handle.clone(), result.get_handle()); + result + } } } impl Clone for BigInt { fn clone(&self) -> Self { let api = M::managed_type_impl(); - let clone_handle: M::BigIntHandle = use_raw_handle(M::static_var_api_impl().next_handle()); - api.bi_set_int64(clone_handle.clone(), 0); - api.bi_add( - clone_handle.clone(), - clone_handle.clone(), - self.handle.clone(), - ); - BigInt::from_handle(clone_handle) + unsafe { + let result = BigInt::new_uninit(); + api.bi_set_int64(result.get_handle(), 0); + api.bi_add( + result.get_handle(), + result.get_handle(), + self.handle.clone(), + ); + result + } } } impl BigInt { pub fn from_biguint(sign: Sign, unsigned: BigUint) -> Self { - let api = M::managed_type_impl(); + let result = unsigned.into_big_int(); if sign.is_minus() { - api.bi_neg(unsigned.value.handle.clone(), unsigned.value.handle.clone()); + M::managed_type_impl().bi_neg(result.handle.clone(), result.handle.clone()); } - BigInt::from_handle(unsigned.value.handle) + result } /// Returns the sign of the `BigInt` as a `Sign`. @@ -234,10 +268,11 @@ impl BigInt { /// Returns the magnitude of the `BigInt` as a `BigUint`. pub fn magnitude(&self) -> BigUint { - let api = M::managed_type_impl(); - let result_handle: M::BigIntHandle = use_raw_handle(M::static_var_api_impl().next_handle()); - api.bi_abs(result_handle.clone(), self.handle.clone()); - BigUint::from_handle(result_handle) + unsafe { + let result = BigUint::new_uninit(); + M::managed_type_impl().bi_abs(result.get_handle(), self.get_handle()); + result + } } /// Convert this `BigInt` into its `Sign` and `BigUint` magnitude, @@ -252,7 +287,7 @@ impl BigInt { /// /// If the number is negative, undefined behavior might occur further down the execution. pub unsafe fn into_big_uint_unchecked(self) -> BigUint { - BigUint::from_handle(self.handle) + BigUint { value: self } } /// Converts this `BigInt` into a `BigUint`, if it's not negative. @@ -327,10 +362,12 @@ impl TopDecode for BigInt { impl BigInt { #[must_use] pub fn pow(&self, exp: u32) -> Self { - let result_handle: M::BigIntHandle = use_raw_handle(M::static_var_api_impl().next_handle()); let exp_handle = BigUint::::make_temp(const_handles::BIG_INT_TEMPORARY_1, exp); - M::managed_type_impl().bi_pow(result_handle.clone(), self.handle.clone(), exp_handle); - BigInt::from_handle(result_handle) + unsafe { + let result = BigInt::new_uninit(); + M::managed_type_impl().bi_pow(result.get_handle(), self.get_handle(), exp_handle); + result + } } } @@ -338,9 +375,9 @@ impl SCDisplay for BigInt { fn fmt(&self, f: &mut F) { let str_handle: M::ManagedBufferHandle = use_raw_handle(const_handles::MBUF_TEMPORARY_1); M::managed_type_impl().bi_to_string(self.handle.clone(), str_handle.clone()); - f.append_managed_buffer(&ManagedBuffer::from_handle( - str_handle.cast_or_signal_error::(), - )); + let cast_handle = str_handle.cast_or_signal_error::(); + let wrap_cast = unsafe { ManagedRef::wrap_handle(cast_handle) }; + f.append_managed_buffer(&wrap_cast); } } diff --git a/framework/base/src/types/managed/basic/big_int_operators.rs b/framework/base/src/types/managed/basic/big_int_operators.rs index fed47d5a26..9edf670cb9 100644 --- a/framework/base/src/types/managed/basic/big_int_operators.rs +++ b/framework/base/src/types/managed/basic/big_int_operators.rs @@ -3,7 +3,7 @@ use core::ops::{ }; use crate::{ - api::{use_raw_handle, BigIntApiImpl, ManagedTypeApi, StaticVarApiImpl}, + api::{BigIntApiImpl, ManagedTypeApi}, types::{BigInt, BigUint, ManagedType, Sign}, }; @@ -19,7 +19,7 @@ macro_rules! binary_operator { self.handle.clone(), other.handle.clone(), ); - BigInt::from_handle(self.handle.clone()) + self } } @@ -44,14 +44,15 @@ macro_rules! binary_operator { fn $method(self, other: &BigInt) -> BigInt { let api = M::managed_type_impl(); - let result_handle: M::BigIntHandle = - use_raw_handle(M::static_var_api_impl().next_handle()); - api.$api_func( - result_handle.clone(), - self.handle.clone(), - other.handle.clone(), - ); - BigInt::from_handle(result_handle) + unsafe { + let result = BigInt::new_uninit(); + api.$api_func( + result.get_handle(), + self.handle.clone(), + other.handle.clone(), + ); + result + } } } @@ -59,7 +60,7 @@ macro_rules! binary_operator { type Output = BigInt; fn $method(self, other: &BigUint) -> BigInt { - self.$method(&BigInt::from_handle(other.get_handle())) + self.$method(other.as_big_int()) } } @@ -67,7 +68,7 @@ macro_rules! binary_operator { type Output = BigInt; fn $method(self, other: &BigInt) -> BigInt { - (&BigInt::from_handle(self.get_handle())).$method(other) + self.as_big_int().$method(other) } } }; @@ -117,9 +118,10 @@ impl Neg for BigInt { type Output = BigInt; fn neg(self) -> Self::Output { - let api = M::managed_type_impl(); - let result_handle: M::BigIntHandle = use_raw_handle(M::static_var_api_impl().next_handle()); - api.bi_neg(result_handle.clone(), self.handle); - BigInt::from_handle(result_handle) + unsafe { + let result = BigInt::new_uninit(); + M::managed_type_impl().bi_neg(result.get_handle(), self.handle); + result + } } } diff --git a/framework/base/src/types/managed/basic/elliptic_curve.rs b/framework/base/src/types/managed/basic/elliptic_curve.rs index 99189d06c5..9b86dba5d1 100644 --- a/framework/base/src/types/managed/basic/elliptic_curve.rs +++ b/framework/base/src/types/managed/basic/elliptic_curve.rs @@ -35,7 +35,7 @@ pub struct EllipticCurve { impl ManagedType for EllipticCurve { type OwnHandle = M::EllipticCurveHandle; - fn from_handle(handle: M::EllipticCurveHandle) -> Self { + unsafe fn from_handle(handle: M::EllipticCurveHandle) -> Self { EllipticCurve { handle } } @@ -43,20 +43,32 @@ impl ManagedType for EllipticCurve { self.handle.clone() } + unsafe fn forget_into_handle(self) -> Self::OwnHandle { + unsafe { + let handle = core::ptr::read(&self.handle); + core::mem::forget(self); + handle + } + } + fn transmute_from_handle_ref(handle_ref: &M::EllipticCurveHandle) -> &Self { unsafe { core::mem::transmute(handle_ref) } } + + fn transmute_from_handle_ref_mut(handle_ref: &mut M::EllipticCurveHandle) -> &mut Self { + unsafe { core::mem::transmute(handle_ref) } + } } impl EllipticCurve { pub fn from_name(name: &ManagedBuffer) -> Self { let handle = M::managed_type_impl().ec_create_from_name_mb(name.get_handle()); - EllipticCurve::from_handle(handle) + unsafe { EllipticCurve::from_handle(handle) } } pub fn from_name_str(name: &str) -> Self { let handle = M::managed_type_impl().ec_create_from_name_bytes(name.as_bytes()); - EllipticCurve::from_handle(handle) + unsafe { EllipticCurve::from_handle(handle) } } pub fn from_bitsize(bitsize: u32) -> Option { @@ -84,14 +96,16 @@ impl EllipticCurve { x_base_point_handle.clone(), y_base_point_handle.clone(), ); - ( - BigUint::from_handle(field_order_handle), - BigUint::from_handle(base_point_order_handle), - BigUint::from_handle(eq_constant_handle), - BigUint::from_handle(x_base_point_handle), - BigUint::from_handle(y_base_point_handle), - api.ec_curve_length(self.handle.clone()), - ) + unsafe { + ( + BigUint::from_handle(field_order_handle), + BigUint::from_handle(base_point_order_handle), + BigUint::from_handle(eq_constant_handle), + BigUint::from_handle(x_base_point_handle), + BigUint::from_handle(y_base_point_handle), + api.ec_curve_length(self.handle.clone()), + ) + } } pub fn get_curve_length(&self) -> u32 { @@ -123,10 +137,12 @@ impl EllipticCurve { x_second_point.value.handle, y_second_point.value.handle, ); - ( - BigUint::from_handle(x_result_handle), - BigUint::from_handle(y_result_handle), - ) + unsafe { + ( + BigUint::from_handle(x_result_handle), + BigUint::from_handle(y_result_handle), + ) + } } pub fn double(&self, x_point: BigUint, y_point: BigUint) -> (BigUint, BigUint) { @@ -140,10 +156,12 @@ impl EllipticCurve { x_point.value.handle, y_point.value.handle, ); - ( - BigUint::from_handle(x_result_handle), - BigUint::from_handle(y_result_handle), - ) + unsafe { + ( + BigUint::from_handle(x_result_handle), + BigUint::from_handle(y_result_handle), + ) + } } pub fn is_on_curve(&self, x_point: BigUint, y_point: BigUint) -> bool { @@ -173,10 +191,12 @@ impl EllipticCurve { y_point.value.handle, data, ); - ( - BigUint::from_handle(x_result_handle), - BigUint::from_handle(y_result_handle), - ) + unsafe { + ( + BigUint::from_handle(x_result_handle), + BigUint::from_handle(y_result_handle), + ) + } } pub fn scalar_mult( @@ -196,10 +216,12 @@ impl EllipticCurve { y_point.value.handle, data.get_handle(), ); - ( - BigUint::from_handle(x_result_handle), - BigUint::from_handle(y_result_handle), - ) + unsafe { + ( + BigUint::from_handle(x_result_handle), + BigUint::from_handle(y_result_handle), + ) + } } #[deprecated( @@ -216,10 +238,12 @@ impl EllipticCurve { self.handle.clone(), data, ); - ( - BigUint::from_handle(x_result_handle), - BigUint::from_handle(y_result_handle), - ) + unsafe { + ( + BigUint::from_handle(x_result_handle), + BigUint::from_handle(y_result_handle), + ) + } } pub fn scalar_base_mult(&self, data: &ManagedBuffer) -> (BigUint, BigUint) { @@ -232,10 +256,12 @@ impl EllipticCurve { self.handle.clone(), data.get_handle(), ); - ( - BigUint::from_handle(x_result_handle), - BigUint::from_handle(y_result_handle), - ) + unsafe { + ( + BigUint::from_handle(x_result_handle), + BigUint::from_handle(y_result_handle), + ) + } } #[deprecated(since = "0.41.0", note = "Please use method `marshal` instead.")] @@ -262,7 +288,7 @@ impl EllipticCurve { y_pair.value.handle, result_handle.clone(), ); - ManagedBuffer::from_handle(result_handle) + unsafe { ManagedBuffer::from_handle(result_handle) } } #[deprecated( @@ -292,7 +318,7 @@ impl EllipticCurve { y_pair.value.handle, result_handle.clone(), ); - ManagedBuffer::from_handle(result_handle) + unsafe { ManagedBuffer::from_handle(result_handle) } } #[deprecated(since = "0.41.0", note = "Please use method `unmarshal` instead.")] @@ -306,10 +332,12 @@ impl EllipticCurve { self.handle.clone(), data, ); - ( - BigUint::from_handle(x_pair_handle), - BigUint::from_handle(y_pair_handle), - ) + unsafe { + ( + BigUint::from_handle(x_pair_handle), + BigUint::from_handle(y_pair_handle), + ) + } } pub fn unmarshal(&self, data: &ManagedBuffer) -> (BigUint, BigUint) { @@ -322,10 +350,12 @@ impl EllipticCurve { self.handle.clone(), data.get_handle(), ); - ( - BigUint::from_handle(x_pair_handle), - BigUint::from_handle(y_pair_handle), - ) + unsafe { + ( + BigUint::from_handle(x_pair_handle), + BigUint::from_handle(y_pair_handle), + ) + } } #[deprecated( @@ -342,10 +372,12 @@ impl EllipticCurve { self.handle.clone(), data, ); - ( - BigUint::from_handle(x_pair_handle), - BigUint::from_handle(y_pair_handle), - ) + unsafe { + ( + BigUint::from_handle(x_pair_handle), + BigUint::from_handle(y_pair_handle), + ) + } } pub fn unmarshal_compressed(&self, data: &ManagedBuffer) -> (BigUint, BigUint) { @@ -358,10 +390,12 @@ impl EllipticCurve { self.handle.clone(), data.get_handle(), ); - ( - BigUint::from_handle(x_pair_handle), - BigUint::from_handle(y_pair_handle), - ) + unsafe { + ( + BigUint::from_handle(x_pair_handle), + BigUint::from_handle(y_pair_handle), + ) + } } #[deprecated(since = "0.41.0", note = "Please use method `generate_key` instead.")] @@ -375,11 +409,13 @@ impl EllipticCurve { y_pub_key_handle.clone(), self.handle.clone(), ); - ( - BigUint::from_handle(x_pub_key_handle), - BigUint::from_handle(y_pub_key_handle), - private_key, - ) + unsafe { + ( + BigUint::from_handle(x_pub_key_handle), + BigUint::from_handle(y_pub_key_handle), + private_key, + ) + } } pub fn generate_key(&self) -> (BigUint, BigUint, ManagedBuffer) { @@ -394,11 +430,13 @@ impl EllipticCurve { self.handle.clone(), private_key_handle.clone(), ); - ( - BigUint::from_handle(x_pub_key_handle), - BigUint::from_handle(y_pub_key_handle), - ManagedBuffer::from_handle(private_key_handle), - ) + unsafe { + ( + BigUint::from_handle(x_pub_key_handle), + BigUint::from_handle(y_pub_key_handle), + ManagedBuffer::from_handle(private_key_handle), + ) + } } } diff --git a/framework/base/src/types/managed/basic/managed_buffer.rs b/framework/base/src/types/managed/basic/managed_buffer.rs index de2dc63bb8..d3c0c28e38 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::{ use_raw_handle, ErrorApiImpl, HandleConstraints, InvalidSliceError, ManagedBufferApiImpl, - ManagedTypeApi, StaticVarApiImpl, + ManagedTypeApi, RawHandle, StaticVarApiImpl, }, codec::{ DecodeErrorHandler, Empty, EncodeErrorHandler, NestedDecode, NestedDecodeInput, @@ -13,7 +13,10 @@ use crate::{ hex_util::encode_bytes_as_hex, FormatBuffer, FormatByteReceiver, SCBinary, SCDisplay, SCLowerHex, }, - types::{heap::BoxedBytes, ManagedBufferCachedBuilder, ManagedType, StaticBufferRef}, + types::{ + heap::BoxedBytes, ManagedBufferCachedBuilder, ManagedRef, ManagedRefMut, ManagedType, + StaticBufferRef, + }, }; /// A byte buffer managed by an external API. @@ -26,7 +29,7 @@ impl ManagedType for ManagedBuffer { type OwnHandle = M::ManagedBufferHandle; #[inline] - fn from_handle(handle: M::ManagedBufferHandle) -> Self { + unsafe fn from_handle(handle: M::ManagedBufferHandle) -> Self { ManagedBuffer { handle } } @@ -34,37 +37,80 @@ impl ManagedType for ManagedBuffer { self.handle.clone() } + unsafe fn forget_into_handle(self) -> Self::OwnHandle { + unsafe { + let handle = core::ptr::read(&self.handle); + core::mem::forget(self); + handle + } + } + fn transmute_from_handle_ref(handle_ref: &M::ManagedBufferHandle) -> &Self { unsafe { core::mem::transmute(handle_ref) } } + + fn transmute_from_handle_ref_mut(handle_ref: &mut M::ManagedBufferHandle) -> &mut Self { + unsafe { core::mem::transmute(handle_ref) } + } } impl ManagedBuffer { #[inline] pub fn new() -> Self { - let new_handle: M::ManagedBufferHandle = - use_raw_handle(M::static_var_api_impl().next_handle()); - // TODO: remove after VM no longer crashes with "unknown handle": - M::managed_type_impl().mb_overwrite(new_handle.clone(), &[]); - ManagedBuffer::from_handle(new_handle) + Self::new_from_bytes(&[]) } #[inline] pub fn new_from_bytes(bytes: &[u8]) -> Self { - let new_handle: M::ManagedBufferHandle = - use_raw_handle(M::static_var_api_impl().next_handle()); - M::managed_type_impl().mb_overwrite(new_handle.clone(), bytes); - ManagedBuffer::from_handle(new_handle) + unsafe { + let result = Self::new_uninit(); + M::managed_type_impl().mb_overwrite(result.get_handle(), bytes); + result + } } #[inline] pub fn new_random(nr_bytes: usize) -> Self { + unsafe { + let result = Self::new_uninit(); + M::managed_type_impl().mb_set_random(result.get_handle(), nr_bytes); + result + } + } + + /// Creates a new object, without initializing it. + /// + /// ## Safety + /// + /// The value needs to be initialized after creation, otherwise the VM will halt the first time the value is attempted to be read. + pub unsafe fn new_uninit() -> Self { let new_handle: M::ManagedBufferHandle = use_raw_handle(M::static_var_api_impl().next_handle()); - M::managed_type_impl().mb_set_random(new_handle.clone(), nr_bytes); ManagedBuffer::from_handle(new_handle) } + /// Creates a shared managed reference to a given raw handle. + /// + /// ## Safety + /// + /// The reference points to a shared value. Make sure the handle is not leaked. + pub unsafe fn temp_const_ref( + raw_handle: RawHandle, + ) -> ManagedRef<'static, M, ManagedBuffer> { + ManagedRef::wrap_handle(use_raw_handle(raw_handle)) + } + + /// Creates a shared managed reference to a given raw handle. + /// + /// ## Safety + /// + /// The reference points to a shared value. Make sure the handle is not leaked. + pub unsafe fn temp_const_ref_mut( + raw_handle: RawHandle, + ) -> ManagedRefMut<'static, M, ManagedBuffer> { + ManagedRefMut::wrap_handle(use_raw_handle(raw_handle)) + } + fn load_static_cache(&self) -> StaticBufferRef where M: ManagedTypeApi, @@ -233,7 +279,7 @@ impl ManagedBuffer { result_handle.clone(), ); if err_result.is_ok() { - Some(ManagedBuffer::from_handle(result_handle)) + Some(unsafe { ManagedBuffer::from_handle(result_handle) }) } else { None } @@ -346,7 +392,7 @@ impl Clone for ManagedBuffer { let api = M::managed_type_impl(); let clone_handle = api.mb_new_empty(); api.mb_append(clone_handle.clone(), self.handle.clone()); - ManagedBuffer::from_handle(clone_handle) + unsafe { ManagedBuffer::from_handle(clone_handle) } } } @@ -476,9 +522,9 @@ impl TypeAbi for ManagedBuffer { impl SCDisplay for ManagedBuffer { fn fmt(&self, f: &mut F) { - f.append_managed_buffer(&ManagedBuffer::from_handle( - self.get_handle().cast_or_signal_error::(), - )); + let cast_handle = self.get_handle().cast_or_signal_error::(); + let wrap_cast = unsafe { ManagedRef::wrap_handle(cast_handle) }; + f.append_managed_buffer(&wrap_cast); } } @@ -487,18 +533,18 @@ impl SCLowerHex for ManagedBuffer { let hex_handle: M::ManagedBufferHandle = use_raw_handle(crate::api::const_handles::MBUF_TEMPORARY_1); M::managed_type_impl().mb_to_hex(self.handle.clone(), hex_handle.clone()); - f.append_managed_buffer(&ManagedBuffer::from_handle( - hex_handle.cast_or_signal_error::(), - )); + let cast_handle = hex_handle.cast_or_signal_error::(); + let wrap_cast = unsafe { ManagedRef::wrap_handle(cast_handle) }; + f.append_managed_buffer(&wrap_cast); } } impl SCBinary for ManagedBuffer { fn fmt(&self, f: &mut F) { // TODO: in Rust thr `0b` prefix appears only when writing "{:#x}", not "{:x}" - f.append_managed_buffer_binary(&ManagedBuffer::from_handle( - self.get_handle().cast_or_signal_error::(), - )); + let cast_handle = self.get_handle().cast_or_signal_error::(); + let wrap_cast = unsafe { ManagedRef::wrap_handle(cast_handle) }; + f.append_managed_buffer_binary(&wrap_cast); } } diff --git a/framework/base/src/types/managed/basic/managed_map.rs b/framework/base/src/types/managed/basic/managed_map.rs index 1f0c0be867..2fce9deb76 100644 --- a/framework/base/src/types/managed/basic/managed_map.rs +++ b/framework/base/src/types/managed/basic/managed_map.rs @@ -1,5 +1,5 @@ use crate::{ - api::{use_raw_handle, ManagedMapApiImpl, ManagedTypeApi, StaticVarApiImpl}, + api::{ManagedMapApiImpl, ManagedTypeApi}, types::ManagedType, }; @@ -15,7 +15,7 @@ impl ManagedType for ManagedMap { type OwnHandle = M::ManagedMapHandle; #[inline] - fn from_handle(handle: M::ManagedMapHandle) -> Self { + unsafe fn from_handle(handle: M::ManagedMapHandle) -> Self { ManagedMap { handle } } @@ -23,15 +23,27 @@ impl ManagedType for ManagedMap { self.handle.clone() } + unsafe fn forget_into_handle(self) -> Self::OwnHandle { + unsafe { + let handle = core::ptr::read(&self.handle); + core::mem::forget(self); + handle + } + } + fn transmute_from_handle_ref(handle_ref: &M::ManagedMapHandle) -> &Self { unsafe { core::mem::transmute(handle_ref) } } + + fn transmute_from_handle_ref_mut(handle_ref: &mut M::ManagedMapHandle) -> &mut Self { + unsafe { core::mem::transmute(handle_ref) } + } } impl ManagedMap { pub fn new() -> Self { let new_handle = M::managed_type_impl().mm_new(); - ManagedMap::from_handle(new_handle) + unsafe { ManagedMap::from_handle(new_handle) } } } @@ -44,10 +56,15 @@ impl Default for ManagedMap { impl ManagedMap { pub fn get(&self, key: &ManagedBuffer) -> ManagedBuffer { - let new_handle: M::ManagedBufferHandle = - use_raw_handle(M::static_var_api_impl().next_handle()); - M::managed_type_impl().mm_get(self.handle.clone(), key.handle.clone(), new_handle.clone()); - ManagedBuffer::from_handle(new_handle) + unsafe { + let result = ManagedBuffer::new_uninit(); + M::managed_type_impl().mm_get( + self.handle.clone(), + key.handle.clone(), + result.get_handle(), + ); + result + } } pub fn put(&mut self, key: &ManagedBuffer, value: &ManagedBuffer) { @@ -59,14 +76,15 @@ impl ManagedMap { } pub fn remove(&mut self, key: &ManagedBuffer) -> ManagedBuffer { - let new_handle: M::ManagedBufferHandle = - use_raw_handle(M::static_var_api_impl().next_handle()); - M::managed_type_impl().mm_remove( - self.handle.clone(), - key.handle.clone(), - new_handle.clone(), - ); - ManagedBuffer::from_handle(new_handle) + unsafe { + let result = ManagedBuffer::new_uninit(); + M::managed_type_impl().mm_remove( + self.handle.clone(), + key.handle.clone(), + result.get_handle(), + ); + result + } } pub fn contains(&self, key: &ManagedBuffer) -> bool { diff --git a/framework/base/src/types/managed/managed_type_trait.rs b/framework/base/src/types/managed/managed_type_trait.rs index ae9b48e4d0..8b30fb8400 100644 --- a/framework/base/src/types/managed/managed_type_trait.rs +++ b/framework/base/src/types/managed/managed_type_trait.rs @@ -7,12 +7,27 @@ pub trait ManagedType: Sized { type OwnHandle: HandleConstraints; #[doc(hidden)] - fn from_handle(handle: Self::OwnHandle) -> Self; + unsafe fn from_handle(handle: Self::OwnHandle) -> Self; fn get_handle(&self) -> Self::OwnHandle; + /// Forgets current object (does not run destructor), but extracts the handle. + /// + /// The handle remains an owned object, so the handle's destructor will run later, when dropped. + /// + /// ## Safety + /// + /// Destructures the object, without running a constructor. + /// + /// To avoid a memory leak, it is necessary for the object to be later + /// reconstructed from handle and its destructor run. + /// + /// It is designed to be used ManagedVec and ManagedOption, + /// where items are dropped later, together with their container. + unsafe fn forget_into_handle(self) -> Self::OwnHandle; + #[doc(hidden)] - fn from_raw_handle(handle: RawHandle) -> Self { + unsafe fn from_raw_handle(handle: RawHandle) -> Self { Self::from_handle(Self::OwnHandle::new(handle)) } @@ -26,6 +41,8 @@ pub trait ManagedType: Sized { /// For types that just wrap another managed type it is easier, call for the wrapped object. fn transmute_from_handle_ref(handle_ref: &Self::OwnHandle) -> &Self; + fn transmute_from_handle_ref_mut(handle_ref: &mut Self::OwnHandle) -> &mut Self; + fn as_ref(&self) -> ManagedRef<'_, M, Self> { ManagedRef::new(self) } 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 1ebc5d5fe7..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 @@ -4,6 +4,7 @@ use crate::{ multi_types::MultiValue3, DecodeErrorHandler, EncodeErrorHandler, TopDecodeMulti, TopDecodeMultiInput, TopDecodeMultiLength, TopEncodeMulti, TopEncodeMultiOutput, }, + types::ManagedVecRef, }; use crate::{ @@ -42,23 +43,18 @@ 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>; - #[inline] - fn from_byte_reader(reader: Reader) -> Self { - EsdtTokenPayment::from_byte_reader(reader).into() + fn read_from_payload(payload: &Self::PAYLOAD) -> Self { + EsdtTokenPayment::read_from_payload(payload).into() } - #[inline] - unsafe fn from_byte_reader_as_borrow<'a, Reader: FnMut(&mut [u8])>( - reader: Reader, - ) -> Self::Ref<'a> { - Self::from_byte_reader(reader) + unsafe fn borrow_from_payload<'a>(payload: &Self::PAYLOAD) -> Self::Ref<'a> { + ManagedVecRef::new(Self::read_from_payload(payload)) } - #[inline] - fn into_byte_writer R>(self, writer: Writer) -> R { - self.obj.into_byte_writer(writer) + fn save_to_payload(self, payload: &mut Self::PAYLOAD) { + self.obj.save_to_payload(payload); } } 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 4dd29166e0..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,37 +87,21 @@ where T: ManagedVecItem + TopEncode + 'static, { #[inline] - #[rustfmt::skip] fn from(v: ManagedVec) -> Self { try_cast_execute_or_else( v, MultiValueEncoded::from_raw_vec, - |v| MultiValueEncoded::from(&v), + MultiValueEncoded::from_iter, ) } } -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, { pub fn to_arg_buffer(&self) -> ManagedArgBuffer { - ManagedArgBuffer::from_handle(self.raw_buffers.get_handle()) + unsafe { ManagedArgBuffer::from_handle(self.raw_buffers.get_handle()) } } } @@ -181,7 +165,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 +182,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_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, + data_loader: ManagedVecOwnedIterator>, _phantom: PhantomData, } @@ -29,7 +29,7 @@ where { pub(crate) fn new(raw_buffers: ManagedVec>) -> 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 { - if self.data_loader.has_next() { - let arg_id = ArgId::from(&b"var args"[..]); - let h = ArgErrorHandler::::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::::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/multi_value/multi_value_managed_vec.rs b/framework/base/src/types/managed/multi_value/multi_value_managed_vec.rs index a168711af1..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 @@ -1,3 +1,5 @@ +use core::borrow::Borrow; + use multiversx_sc_codec::multi_types::MultiValueVec; use crate::{ @@ -7,7 +9,7 @@ use crate::{ DecodeErrorHandler, EncodeErrorHandler, TopDecodeMulti, TopDecodeMultiInput, TopEncodeMulti, TopEncodeMultiOutput, Vec, }, - types::ManagedType, + types::{ManagedType, ManagedVecOwnedIterator}, }; use crate::types::{ManagedVec, ManagedVecItem, ManagedVecRefIterator}; @@ -46,7 +48,7 @@ where type OwnHandle = M::ManagedBufferHandle; #[inline] - fn from_handle(handle: M::ManagedBufferHandle) -> Self { + unsafe fn from_handle(handle: M::ManagedBufferHandle) -> Self { Self(ManagedVec::from_handle(handle)) } @@ -54,9 +56,17 @@ where self.0.get_handle() } + unsafe fn forget_into_handle(self) -> Self::OwnHandle { + self.0.forget_into_handle() + } + fn transmute_from_handle_ref(handle_ref: &M::ManagedBufferHandle) -> &Self { unsafe { core::mem::transmute(handle_ref) } } + + fn transmute_from_handle_ref_mut(handle_ref: &mut M::ManagedBufferHandle) -> &mut Self { + unsafe { core::mem::transmute(handle_ref) } + } } impl MultiValueManagedVec @@ -134,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, @@ -173,8 +197,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 a46016e69a..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, @@ -98,18 +100,16 @@ where const SKIPS_RESERIALIZATION: bool = false; type Ref<'a> = Self; - fn from_byte_reader(reader: Reader) -> Self { - Self::from(ManagedVec::::from_byte_reader(reader)) + fn read_from_payload(payload: &Self::PAYLOAD) -> Self { + Self::from(ManagedVec::::read_from_payload(payload)) } - unsafe fn from_byte_reader_as_borrow<'a, Reader: FnMut(&mut [u8])>( - reader: Reader, - ) -> Self::Ref<'a> { - Self::from_byte_reader(reader) + unsafe fn borrow_from_payload<'a>(payload: &Self::PAYLOAD) -> Self::Ref<'a> { + Self::read_from_payload(payload) } - fn into_byte_writer R>(self, writer: Writer) -> R { - self.contents.into_byte_writer(writer) + fn save_to_payload(self, payload: &mut Self::PAYLOAD) { + self.contents.save_to_payload(payload); } } @@ -124,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/mod.rs b/framework/base/src/types/managed/wrapped.rs similarity index 77% rename from framework/base/src/types/managed/wrapped/mod.rs rename to framework/base/src/types/managed/wrapped.rs index 1874dc48b0..52d827c79f 100644 --- a/framework/base/src/types/managed/wrapped/mod.rs +++ b/framework/base/src/types/managed/wrapped.rs @@ -14,13 +14,16 @@ mod managed_byte_array; mod managed_decimal; mod managed_option; mod managed_ref; +mod managed_ref_mut; mod managed_vec; mod managed_vec_item; mod managed_vec_item_nested_tuple; mod managed_vec_item_payload; -mod managed_vec_owned_iter; +mod managed_vec_iter_owned; +mod managed_vec_iter_payload; +mod managed_vec_iter_ref; mod managed_vec_ref; -mod managed_vec_ref_iter; +mod managed_vec_ref_mut; pub(crate) mod preloaded_managed_buffer; mod randomness_source; mod token_identifier; @@ -43,13 +46,19 @@ pub use managed_decimal::{ }; pub use managed_option::ManagedOption; pub use managed_ref::ManagedRef; +pub use managed_ref_mut::ManagedRefMut; pub use managed_vec::ManagedVec; -pub use managed_vec_item::ManagedVecItem; +pub use managed_vec_item::{ + managed_vec_item_read_from_payload_index, managed_vec_item_save_to_payload_index, + ManagedVecItem, +}; 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_iter_owned::ManagedVecOwnedIterator; +pub use managed_vec_iter_payload::ManagedVecPayloadIterator; +pub use managed_vec_iter_ref::ManagedVecRefIterator; 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; pub use token_identifier::TokenIdentifier; diff --git a/framework/base/src/types/managed/wrapped/big_uint.rs b/framework/base/src/types/managed/wrapped/big_uint.rs index 615d790480..8151110315 100644 --- a/framework/base/src/types/managed/wrapped/big_uint.rs +++ b/framework/base/src/types/managed/wrapped/big_uint.rs @@ -4,7 +4,7 @@ use crate::{ abi::{TypeAbi, TypeAbiFrom, TypeName}, api::{ const_handles, use_raw_handle, BigIntApiImpl, HandleConstraints, ManagedBufferApiImpl, - ManagedTypeApi, ManagedTypeApiImpl, RawHandle, StaticVarApiImpl, + ManagedTypeApi, ManagedTypeApiImpl, RawHandle, }, codec::{ DecodeErrorHandler, EncodeErrorHandler, NestedDecode, NestedDecodeInput, NestedEncode, @@ -26,7 +26,7 @@ pub struct BigUint { impl ManagedType for BigUint { type OwnHandle = M::BigIntHandle; - fn from_handle(handle: M::BigIntHandle) -> Self { + unsafe fn from_handle(handle: M::BigIntHandle) -> Self { BigUint { value: BigInt::from_handle(handle), } @@ -36,9 +36,17 @@ impl ManagedType for BigUint { self.value.handle.clone() } + unsafe fn forget_into_handle(self) -> Self::OwnHandle { + self.value.forget_into_handle() + } + fn transmute_from_handle_ref(handle_ref: &M::BigIntHandle) -> &Self { unsafe { core::mem::transmute(handle_ref) } } + + fn transmute_from_handle_ref_mut(handle_ref: &mut M::BigIntHandle) -> &mut Self { + unsafe { core::mem::transmute(handle_ref) } + } } impl From for BigUint { @@ -62,6 +70,17 @@ impl From<&ManagedBuffer> for BigUint { } impl BigUint { + /// Creates a new object, without initializing it. + /// + /// ## Safety + /// + /// The value needs to be initialized after creation, otherwise the VM will halt the first time the value is attempted to be read. + pub unsafe fn new_uninit() -> Self { + BigUint { + value: BigInt::new_uninit(), + } + } + pub(crate) fn set_value(handle: M::BigIntHandle, value: T) where T: TryInto + num_traits::Unsigned, @@ -73,9 +92,11 @@ impl BigUint { where T: TryInto + num_traits::Unsigned, { - let handle: M::BigIntHandle = use_raw_handle(M::static_var_api_impl().next_handle()); - Self::set_value(handle.clone(), value); - BigUint::from_handle(handle) + unsafe { + let result = Self::new_uninit(); + Self::set_value(result.get_handle(), value); + result + } } pub(crate) fn make_temp(handle: RawHandle, value: T) -> M::BigIntHandle @@ -169,9 +190,11 @@ impl Default for BigUint { impl BigUint { #[inline] pub fn zero() -> Self { - let handle: M::BigIntHandle = use_raw_handle(M::static_var_api_impl().next_handle()); - M::managed_type_impl().bi_set_int64(handle.clone(), 0); - BigUint::from_handle(handle) + unsafe { + let result = Self::new_uninit(); + M::managed_type_impl().bi_set_int64(result.get_handle(), 0); + result + } } pub fn zero_ref() -> ManagedRef<'static, M, BigUint> { @@ -191,16 +214,16 @@ impl BigUint { Self::set_value(self.value.handle.clone(), value); } - #[inline] pub fn from_bytes_be(bytes: &[u8]) -> Self { let mb_handle: M::ManagedBufferHandle = use_raw_handle(const_handles::MBUF_TEMPORARY_1); M::managed_type_impl().mb_overwrite(mb_handle.clone(), bytes); - let handle: M::BigIntHandle = use_raw_handle(M::static_var_api_impl().next_handle()); - M::managed_type_impl().mb_to_big_int_unsigned(mb_handle, handle.clone()); - BigUint::from_handle(handle) + unsafe { + let result = Self::new_uninit(); + M::managed_type_impl().mb_to_big_int_unsigned(mb_handle, result.get_handle()); + result + } } - #[inline] pub fn to_bytes_be(&self) -> BoxedBytes { let mb_handle: M::ManagedBufferHandle = use_raw_handle(const_handles::MBUF_TEMPORARY_1); M::managed_type_impl() @@ -208,44 +231,40 @@ impl BigUint { M::managed_type_impl().mb_to_boxed_bytes(mb_handle) } - #[inline] pub fn from_bytes_be_buffer(managed_buffer: &ManagedBuffer) -> Self { - let handle: M::BigIntHandle = use_raw_handle(M::static_var_api_impl().next_handle()); - M::managed_type_impl() - .mb_to_big_int_unsigned(managed_buffer.handle.clone(), handle.clone()); - BigUint::from_handle(handle) + unsafe { + let result = BigUint::new_uninit(); + M::managed_type_impl() + .mb_to_big_int_unsigned(managed_buffer.handle.clone(), result.get_handle()); + result + } } - #[inline] pub fn to_bytes_be_buffer(&self) -> ManagedBuffer { - let mb_handle: M::ManagedBufferHandle = - use_raw_handle(M::static_var_api_impl().next_handle()); - M::managed_type_impl() - .mb_from_big_int_unsigned(self.value.handle.clone(), mb_handle.clone()); - ManagedBuffer::from_handle(mb_handle) + unsafe { + let result = ManagedBuffer::new_uninit(); + M::managed_type_impl().mb_from_big_int_unsigned(self.get_handle(), result.get_handle()); + result + } } } impl BigUint { - #[inline] - #[must_use] pub fn sqrt(&self) -> Self { - let api = M::managed_type_impl(); - let result_handle: M::BigIntHandle = use_raw_handle(M::static_var_api_impl().next_handle()); - api.bi_sqrt(result_handle.clone(), self.value.handle.clone()); - BigUint::from_handle(result_handle) + unsafe { + let result = BigUint::new_uninit(); + M::managed_type_impl().bi_sqrt(result.get_handle(), self.get_handle()); + result + } } - #[must_use] pub fn pow(&self, exp: u32) -> Self { - let result_handle: M::BigIntHandle = use_raw_handle(M::static_var_api_impl().next_handle()); let big_int_temp_1 = BigUint::::make_temp(const_handles::BIG_INT_TEMPORARY_1, exp); - M::managed_type_impl().bi_pow( - result_handle.clone(), - self.value.handle.clone(), - big_int_temp_1, - ); - BigUint::from_handle(result_handle) + unsafe { + let result = BigUint::new_uninit(); + M::managed_type_impl().bi_pow(result.get_handle(), self.get_handle(), big_int_temp_1); + result + } } /// The whole part of the base-2 logarithm. @@ -254,7 +273,6 @@ impl BigUint { /// More specifically, the log2 floor is the position of the most significant bit minus one. /// /// Will return `None` for the number zero (the logarithm in this case would approach -inf). - #[inline] pub fn log2_floor(&self) -> Option { let api = M::managed_type_impl(); let result = api.bi_log2(self.value.handle.clone()); @@ -298,15 +316,7 @@ impl BigUint { impl Clone for BigUint { fn clone(&self) -> Self { - let api = M::managed_type_impl(); - let clone_handle: M::BigIntHandle = use_raw_handle(M::static_var_api_impl().next_handle()); - api.bi_set_int64(clone_handle.clone(), 0); - api.bi_add( - clone_handle.clone(), - clone_handle.clone(), - self.value.handle.clone(), - ); - BigUint::from_handle(clone_handle) + unsafe { self.as_big_int().clone().into_big_uint_unchecked() } } } @@ -372,9 +382,9 @@ impl SCDisplay for BigUint { fn fmt(&self, f: &mut F) { let str_handle: M::ManagedBufferHandle = use_raw_handle(const_handles::MBUF_TEMPORARY_1); M::managed_type_impl().bi_to_string(self.value.handle.clone(), str_handle.clone()); - f.append_managed_buffer(&ManagedBuffer::from_handle( - str_handle.cast_or_signal_error::(), - )); + let cast_handle = str_handle.cast_or_signal_error::(); + let wrap_cast = unsafe { ManagedRef::wrap_handle(cast_handle) }; + f.append_managed_buffer(&wrap_cast); } } diff --git a/framework/base/src/types/managed/wrapped/big_uint_operators.rs b/framework/base/src/types/managed/wrapped/big_uint_operators.rs index 934079eef7..5ca27f783e 100644 --- a/framework/base/src/types/managed/wrapped/big_uint_operators.rs +++ b/framework/base/src/types/managed/wrapped/big_uint_operators.rs @@ -1,5 +1,5 @@ use crate::{ - api::{const_handles, use_raw_handle, BigIntApiImpl, ManagedTypeApi, StaticVarApiImpl}, + api::{const_handles, BigIntApiImpl, ManagedTypeApi}, types::{BigUint, ManagedType}, }; use core::ops::{ @@ -14,11 +14,11 @@ macro_rules! binary_operator { fn $method(self, other: BigUint) -> BigUint { M::managed_type_impl().$api_func( - self.value.handle.clone(), - self.value.handle.clone(), - other.value.handle.clone(), + self.get_handle(), + self.get_handle(), + other.get_handle(), ); - BigUint::from_handle(self.value.handle.clone()) + self } } @@ -26,14 +26,15 @@ macro_rules! binary_operator { type Output = BigUint; fn $method(self, other: &BigUint) -> BigUint { - let result_handle: M::BigIntHandle = - use_raw_handle(M::static_var_api_impl().next_handle()); - M::managed_type_impl().$api_func( - result_handle.clone(), - self.value.handle.clone(), - other.value.handle.clone(), - ); - BigUint::from_handle(result_handle) + unsafe { + let result = BigUint::new_uninit(); + M::managed_type_impl().$api_func( + result.get_handle(), + self.get_handle(), + other.get_handle(), + ); + result + } } } @@ -42,11 +43,11 @@ macro_rules! binary_operator { fn $method(self, other: &BigUint) -> BigUint { M::managed_type_impl().$api_func( - self.value.handle.clone(), - self.value.handle.clone(), - other.value.handle.clone(), + self.get_handle(), + self.get_handle(), + other.get_handle(), ); - BigUint::from_handle(self.value.handle.clone()) + self } } @@ -56,11 +57,11 @@ macro_rules! binary_operator { fn $method(self, other: u32) -> BigUint { let big_int_temp_1 = Self::make_temp(const_handles::BIG_INT_TEMPORARY_1, other); M::managed_type_impl().$api_func( - self.value.handle.clone(), - self.value.handle.clone(), + self.get_handle(), + self.get_handle(), big_int_temp_1, ); - BigUint::from_handle(self.value.handle.clone()) + self } } @@ -70,14 +71,15 @@ macro_rules! binary_operator { fn $method(self, other: u32) -> BigUint { let big_int_temp_1 = BigUint::::make_temp(const_handles::BIG_INT_TEMPORARY_1, other); - let result_handle: M::BigIntHandle = - use_raw_handle(M::static_var_api_impl().next_handle()); - M::managed_type_impl().$api_func( - result_handle.clone(), - self.value.handle.clone(), - big_int_temp_1, - ); - BigUint::from_handle(result_handle) + unsafe { + let result = BigUint::new_uninit(); + M::managed_type_impl().$api_func( + result.get_handle(), + self.get_handle(), + big_int_temp_1, + ); + result + } } } @@ -91,7 +93,7 @@ macro_rules! binary_operator { self.value.handle.clone(), big_int_temp_1, ); - BigUint::from_handle(self.value.handle.clone()) + self } } @@ -101,14 +103,15 @@ macro_rules! binary_operator { fn $method(self, other: u64) -> BigUint { let big_int_temp_1 = BigUint::::make_temp(const_handles::BIG_INT_TEMPORARY_1, other); - let result_handle: M::BigIntHandle = - use_raw_handle(M::static_var_api_impl().next_handle()); - M::managed_type_impl().$api_func( - result_handle.clone(), - self.value.handle.clone(), - big_int_temp_1, - ); - BigUint::from_handle(result_handle) + unsafe { + let result = BigUint::new_uninit(); + M::managed_type_impl().$api_func( + result.get_handle(), + self.get_handle(), + big_int_temp_1, + ); + result + } } } }; @@ -200,14 +203,11 @@ macro_rules! shift_traits { type Output = BigUint; fn $method(self, rhs: usize) -> BigUint { - let result_handle: M::BigIntHandle = - use_raw_handle(M::static_var_api_impl().next_handle()); - M::managed_type_impl().$api_func( - result_handle.clone(), - self.value.handle.clone(), - rhs, - ); - BigUint::from_handle(result_handle) + unsafe { + let result = BigUint::new_uninit(); + M::managed_type_impl().$api_func(result.get_handle(), self.get_handle(), rhs); + result + } } } }; diff --git a/framework/base/src/types/managed/wrapped/egld_or_esdt_token_identifier.rs b/framework/base/src/types/managed/wrapped/egld_or_esdt_token_identifier.rs index 19506645a2..7b46cb2e50 100644 --- a/framework/base/src/types/managed/wrapped/egld_or_esdt_token_identifier.rs +++ b/framework/base/src/types/managed/wrapped/egld_or_esdt_token_identifier.rs @@ -25,7 +25,8 @@ use crate as multiversx_sc; // required by the ManagedVecItem derive /// /// It is, however more optimized than that. Its implementation is based on `ManagedOption`. /// -/// EGLD a special, invalid token identifier handle. This way we can fit it inside a single i32 in memory. +/// EGLD is indicated by a special, invalid token identifier handle. +/// This way we can fit it inside a single i32 in memory. #[repr(transparent)] #[derive(ManagedVecItem, Clone)] pub struct EgldOrEsdtTokenIdentifier { @@ -56,13 +57,6 @@ impl EgldOrEsdtTokenIdentifier { } } - pub fn from_opt_raw_handle(opt_handle: Option) -> Self { - match opt_handle { - Some(handle) => Self::esdt(TokenIdentifier::from_handle(handle)), - None => Self::egld(), - } - } - pub fn parse(data: ManagedBuffer) -> Self { if data == Self::EGLD_REPRESENTATION { Self::egld() @@ -213,11 +207,9 @@ impl TypeAbiFrom<&TokenIdentifier> for EgldOrEsdtTokenIdentifier where impl TypeAbiFrom<&[u8]> for EgldOrEsdtTokenIdentifier where M: ManagedTypeApi {} impl TypeAbiFrom<&str> for EgldOrEsdtTokenIdentifier where M: ManagedTypeApi {} -impl<'a, M> TypeAbiFrom> for EgldOrEsdtTokenIdentifier where - M: ManagedTypeApi -{ -} -impl<'a, M> TypeAbiFrom<&TestTokenIdentifier<'a>> for EgldOrEsdtTokenIdentifier where +impl TypeAbiFrom> for EgldOrEsdtTokenIdentifier where M: ManagedTypeApi +{} +impl TypeAbiFrom<&TestTokenIdentifier<'_>> for EgldOrEsdtTokenIdentifier where M: ManagedTypeApi { } @@ -240,9 +232,9 @@ impl TypeAbi for EgldOrEsdtTokenIdentifier { impl SCDisplay for EgldOrEsdtTokenIdentifier { fn fmt(&self, f: &mut F) { if let Some(token_identifier) = self.data.as_option() { - f.append_managed_buffer(&ManagedBuffer::from_handle( - token_identifier.get_handle().cast_or_signal_error::(), - )); + let cast_handle = token_identifier.get_handle().cast_or_signal_error::(); + let wrap_cast = unsafe { ManagedRef::wrap_handle(cast_handle) }; + f.append_managed_buffer(&wrap_cast); } else { f.append_bytes(Self::EGLD_REPRESENTATION); } @@ -254,9 +246,9 @@ const EGLD_REPRESENTATION_HEX: &[u8] = b"45474C44"; impl SCLowerHex for EgldOrEsdtTokenIdentifier { fn fmt(&self, f: &mut F) { if let Some(token_identifier) = self.data.as_option() { - f.append_managed_buffer_lower_hex(&ManagedBuffer::from_handle( - token_identifier.get_handle().cast_or_signal_error::(), - )); + let cast_handle = token_identifier.get_handle().cast_or_signal_error::(); + let wrap_cast = unsafe { ManagedRef::wrap_handle(cast_handle) }; + f.append_managed_buffer_lower_hex(&wrap_cast); } else { f.append_bytes(EGLD_REPRESENTATION_HEX); } @@ -268,13 +260,15 @@ where M: ManagedTypeApi, { fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { - if let Some(token_identifier) = self.data.as_option() { - let token_id_str = token_identifier.to_string(); - f.debug_tuple("EgldOrEsdtTokenIdentifier::Esdt") - .field(&token_id_str) - .finish() - } else { - f.write_str("EgldOrEsdtTokenIdentifier::Egld") - } + self.map_ref_or_else( + f, + |f| f.write_str("EgldOrEsdtTokenIdentifier::Egld"), + |f, token_identifier| { + let token_id_str = token_identifier.to_string(); + f.debug_tuple("EgldOrEsdtTokenIdentifier::Esdt") + .field(&token_id_str) + .finish() + }, + ) } } diff --git a/framework/base/src/types/managed/wrapped/egld_or_multi_esdt_payment.rs b/framework/base/src/types/managed/wrapped/egld_or_multi_esdt_payment.rs index 88534f95c1..1c06f0677c 100644 --- a/framework/base/src/types/managed/wrapped/egld_or_multi_esdt_payment.rs +++ b/framework/base/src/types/managed/wrapped/egld_or_multi_esdt_payment.rs @@ -49,7 +49,7 @@ impl EgldOrMultiEsdtPayment { } } -impl<'a, M: ManagedTypeApi> EgldOrMultiEsdtPaymentRefs<'a, M> { +impl EgldOrMultiEsdtPaymentRefs<'_, M> { pub fn to_owned_payment(&self) -> EgldOrMultiEsdtPayment { match self { EgldOrMultiEsdtPaymentRefs::Egld(egld_value) => { 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 fd7af7c51f..205a219a2c 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 @@ -1,4 +1,4 @@ -use super::{ManagedVecItem, ManagedVecItemPayload}; +use super::ManagedVecItem; use core::{cmp::Ordering, marker::PhantomData}; pub struct EncodedManagedVecItem @@ -14,9 +14,7 @@ where T: ManagedVecItem, { pub(crate) fn decode(&self) -> T { - T::from_byte_reader(|item_bytes| { - item_bytes.copy_from_slice(self.encoded.payload_slice()); - }) + T::read_from_payload(&self.encoded) } } diff --git a/framework/base/src/types/managed/wrapped/esdt_token_payment.rs b/framework/base/src/types/managed/wrapped/esdt_token_payment.rs index cf2ccf0ceb..041ddd1f64 100644 --- a/framework/base/src/types/managed/wrapped/esdt_token_payment.rs +++ b/framework/base/src/types/managed/wrapped/esdt_token_payment.rs @@ -13,7 +13,10 @@ use crate::{ derive::type_abi, }; -use super::{ManagedVec, ManagedVecItemPayloadBuffer}; +use super::{ + managed_vec_item_read_from_payload_index, managed_vec_item_save_to_payload_index, ManagedVec, + ManagedVecItemPayloadBuffer, ManagedVecRef, +}; #[type_abi] #[derive(TopEncode, NestedEncode, Clone, PartialEq, Eq, Debug)] @@ -153,28 +156,6 @@ impl EsdtTokenPayment { } } -fn managed_vec_item_from_slice(arr: &[u8], index: &mut usize) -> T -where - T: ManagedVecItem, -{ - ManagedVecItem::from_byte_reader(|bytes| { - let size = T::payload_size(); - bytes.copy_from_slice(&arr[*index..*index + size]); - *index += size; - }) -} - -fn managed_vec_item_to_slice(arr: &mut [u8], index: &mut usize, item: T) -where - T: ManagedVecItem, -{ - ManagedVecItem::into_byte_writer(item, |bytes| { - let size = T::payload_size(); - arr[*index..*index + size].copy_from_slice(bytes); - *index += size; - }); -} - impl IntoMultiValue for EsdtTokenPayment { type MultiValue = EsdtTokenPaymentMultiValue; @@ -187,39 +168,31 @@ impl IntoMultiValue for EsdtTokenPayment { impl ManagedVecItem for EsdtTokenPayment { type PAYLOAD = ManagedVecItemPayloadBuffer<16>; const SKIPS_RESERIALIZATION: bool = false; - type Ref<'a> = Self; + type Ref<'a> = ManagedVecRef<'a, Self>; - fn from_byte_reader(mut reader: Reader) -> Self { - let mut arr: [u8; 16] = [0u8; 16]; - reader(&mut arr[..]); + fn read_from_payload(payload: &Self::PAYLOAD) -> Self { let mut index = 0; - - let token_identifier = managed_vec_item_from_slice(&arr, &mut index); - let token_nonce = managed_vec_item_from_slice(&arr, &mut index); - let amount = managed_vec_item_from_slice(&arr, &mut index); - - EsdtTokenPayment { - token_identifier, - token_nonce, - amount, + unsafe { + EsdtTokenPayment { + token_identifier: managed_vec_item_read_from_payload_index(payload, &mut index), + token_nonce: managed_vec_item_read_from_payload_index(payload, &mut index), + amount: managed_vec_item_read_from_payload_index(payload, &mut index), + } } } - unsafe fn from_byte_reader_as_borrow<'a, Reader: FnMut(&mut [u8])>( - reader: Reader, - ) -> Self::Ref<'a> { - Self::from_byte_reader(reader) + unsafe fn borrow_from_payload<'a>(payload: &Self::PAYLOAD) -> Self::Ref<'a> { + ManagedVecRef::new(Self::read_from_payload(payload)) } - fn into_byte_writer R>(self, mut writer: Writer) -> R { - let mut arr: [u8; 16] = [0u8; 16]; + fn save_to_payload(self, payload: &mut Self::PAYLOAD) { let mut index = 0; - managed_vec_item_to_slice(&mut arr, &mut index, self.token_identifier); - managed_vec_item_to_slice(&mut arr, &mut index, self.token_nonce); - managed_vec_item_to_slice(&mut arr, &mut index, self.amount); - - writer(&arr[..]) + unsafe { + managed_vec_item_save_to_payload_index(self.token_identifier, payload, &mut index); + managed_vec_item_save_to_payload_index(self.token_nonce, payload, &mut index); + managed_vec_item_save_to_payload_index(self.amount, payload, &mut index); + } } } diff --git a/framework/base/src/types/managed/wrapped/managed_address.rs b/framework/base/src/types/managed/wrapped/managed_address.rs index a90482fb04..ec3b338961 100644 --- a/framework/base/src/types/managed/wrapped/managed_address.rs +++ b/framework/base/src/types/managed/wrapped/managed_address.rs @@ -2,7 +2,7 @@ use core::convert::{TryFrom, TryInto}; use crate::{ abi::{TypeAbi, TypeAbiFrom, TypeName}, - api::ManagedTypeApi, + api::{use_raw_handle, ManagedTypeApi, RawHandle}, codec::{ DecodeError, DecodeErrorHandler, EncodeErrorHandler, NestedDecode, NestedDecodeInput, NestedEncode, NestedEncodeOutput, TopDecode, TopDecodeInput, TopEncode, TopEncodeOutput, @@ -11,6 +11,8 @@ use crate::{ types::{heap::Address, ManagedBuffer, ManagedByteArray, ManagedType}, }; +use super::ManagedRef; + #[repr(transparent)] #[derive(Clone)] pub struct ManagedAddress { @@ -49,6 +51,28 @@ where } } + /// Creates a new object, without initializing it. + /// + /// ## Safety + /// + /// The value needs to be initialized after creation, otherwise the VM will halt the first time the value is attempted to be read. + pub unsafe fn new_uninit() -> Self { + ManagedAddress { + bytes: ManagedByteArray::new_uninit(), + } + } + + /// Creates a shared managed reference to a given raw handle. + /// + /// ## Safety + /// + /// The reference points to a shared value. Make sure the handle is not leaked. + pub unsafe fn temp_const_ref( + raw_handle: RawHandle, + ) -> ManagedRef<'static, M, ManagedAddress> { + ManagedRef::wrap_handle(use_raw_handle(raw_handle)) + } + #[inline] pub fn as_managed_buffer(&self) -> &ManagedBuffer { self.bytes.as_managed_buffer() @@ -133,7 +157,7 @@ where type OwnHandle = M::ManagedBufferHandle; #[inline] - fn from_handle(handle: M::ManagedBufferHandle) -> Self { + unsafe fn from_handle(handle: M::ManagedBufferHandle) -> Self { ManagedAddress { bytes: ManagedByteArray::from_handle(handle), } @@ -143,9 +167,17 @@ where self.bytes.get_handle() } + unsafe fn forget_into_handle(self) -> Self::OwnHandle { + self.bytes.forget_into_handle() + } + fn transmute_from_handle_ref(handle_ref: &M::ManagedBufferHandle) -> &Self { unsafe { core::mem::transmute(handle_ref) } } + + fn transmute_from_handle_ref_mut(handle_ref: &mut M::ManagedBufferHandle) -> &mut Self { + unsafe { core::mem::transmute(handle_ref) } + } } impl Default for ManagedAddress diff --git a/framework/base/src/types/managed/wrapped/managed_byte_array.rs b/framework/base/src/types/managed/wrapped/managed_byte_array.rs index 83e95d332c..76f292e7e8 100644 --- a/framework/base/src/types/managed/wrapped/managed_byte_array.rs +++ b/framework/base/src/types/managed/wrapped/managed_byte_array.rs @@ -35,7 +35,7 @@ where type OwnHandle = M::ManagedBufferHandle; #[inline] - fn from_handle(handle: M::ManagedBufferHandle) -> Self { + unsafe fn from_handle(handle: M::ManagedBufferHandle) -> Self { ManagedByteArray { buffer: ManagedBuffer::from_handle(handle), } @@ -45,9 +45,17 @@ where self.buffer.get_handle() } + unsafe fn forget_into_handle(self) -> Self::OwnHandle { + self.buffer.forget_into_handle() + } + fn transmute_from_handle_ref(handle_ref: &M::ManagedBufferHandle) -> &Self { unsafe { core::mem::transmute(handle_ref) } } + + fn transmute_from_handle_ref_mut(handle_ref: &mut M::ManagedBufferHandle) -> &mut Self { + unsafe { core::mem::transmute(handle_ref) } + } } impl Default for ManagedByteArray @@ -81,6 +89,17 @@ where } } + /// Creates a new object, without initializing it. + /// + /// ## Safety + /// + /// The value needs to be initialized after creation, otherwise the VM will halt the first time the value is attempted to be read. + pub unsafe fn new_uninit() -> Self { + ManagedByteArray { + buffer: ManagedBuffer::new_uninit(), + } + } + /// Number of items. #[inline] pub fn len(&self) -> usize { diff --git a/framework/base/src/types/managed/wrapped/managed_decimal/managed_decimal_logarithm.rs b/framework/base/src/types/managed/wrapped/managed_decimal/managed_decimal_logarithm.rs index 41f173a50a..43c4debbac 100644 --- a/framework/base/src/types/managed/wrapped/managed_decimal/managed_decimal_logarithm.rs +++ b/framework/base/src/types/managed/wrapped/managed_decimal/managed_decimal_logarithm.rs @@ -2,7 +2,7 @@ use super::decimals::{ConstDecimals, Decimals}; use super::ManagedDecimalSigned; use super::{ManagedDecimal, NumDecimals}; -use crate::proxy_imports::ManagedType; +use crate::types::ManagedRef; use crate::{ api::ManagedTypeApi, contract_base::ErrorHelper, @@ -104,7 +104,7 @@ impl ManagedDecimalSigned { return None; } - let bu = BigUint::from_handle(self.data.handle.clone()); + let bu = unsafe { ManagedRef::wrap_handle(self.data.handle.clone()) }; compute_ln(&bu, self.decimals.num_decimals()) } @@ -118,7 +118,7 @@ impl ManagedDecimalSigned { return None; } - let bu = BigUint::from_handle(self.data.handle.clone()); + let bu = unsafe { ManagedRef::wrap_handle(self.data.handle.clone()) }; compute_log2(&bu, self.decimals.num_decimals()) } } 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 f76bb84414..400963e6b8 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 @@ -6,7 +6,7 @@ use crate::{ }, err_msg, formatter::{FormatBuffer, FormatByteReceiver, SCDisplay}, - types::{BigFloat, BigInt, BigUint, ManagedBuffer, ManagedType, Sign}, + types::{BigFloat, BigInt, BigUint, Sign}, }; use alloc::string::ToString; @@ -354,15 +354,15 @@ pub(super) fn managed_decimal_fmt( if len > num_dec { let temp_str_handle: M::ManagedBufferHandle = use_raw_handle(const_handles::MBUF_TEMPORARY_2); + let cast_handle = temp_str_handle.clone().cast_or_signal_error::(); + let temp_str_ref = unsafe { ManagedRef::wrap_handle(cast_handle) }; let _ = M::managed_type_impl().mb_copy_slice( full_str_handle.clone(), 0, len - num_dec, temp_str_handle.clone(), ); - f.append_managed_buffer(&ManagedBuffer::from_raw_handle( - temp_str_handle.get_raw_handle(), - )); + f.append_managed_buffer(&temp_str_ref); f.append_bytes(b"."); let _ = M::managed_type_impl().mb_copy_slice( full_str_handle.clone(), @@ -370,17 +370,15 @@ pub(super) fn managed_decimal_fmt( num_dec, temp_str_handle.clone(), ); - f.append_managed_buffer(&ManagedBuffer::from_raw_handle( - temp_str_handle.get_raw_handle(), - )); + f.append_managed_buffer(&temp_str_ref); } else { f.append_bytes(b"0."); for _ in len..num_dec { f.append_bytes(b"0"); } - f.append_managed_buffer(&ManagedBuffer::from_raw_handle( - full_str_handle.get_raw_handle(), - )); + let cast_handle = full_str_handle.clone().cast_or_signal_error::(); + let full_str_ref = unsafe { ManagedRef::wrap_handle(cast_handle) }; + f.append_managed_buffer(&full_str_ref); } } diff --git a/framework/base/src/types/managed/wrapped/managed_option.rs b/framework/base/src/types/managed/wrapped/managed_option.rs index e448ae8e88..c7ee9371b9 100644 --- a/framework/base/src/types/managed/wrapped/managed_option.rs +++ b/framework/base/src/types/managed/wrapped/managed_option.rs @@ -2,6 +2,7 @@ use core::marker::PhantomData; use crate::{ abi::TypeAbiFrom, + api::HandleConstraints, codec::{ DecodeErrorHandler, EncodeErrorHandler, NestedDecode, NestedDecodeInput, NestedEncode, NestedEncodeOutput, TopDecode, TopDecodeInput, TopEncode, TopEncodeOutput, @@ -41,7 +42,7 @@ where } pub fn some(value: T) -> Self { - Self::new_with_handle(value.get_handle()) + unsafe { Self::new_with_handle(value.forget_into_handle()) } } pub fn none() -> Self { @@ -143,7 +144,12 @@ where F: FnOnce(Context, &T) -> R, { if self.is_some() { - f(context, &T::from_handle(self.handle.clone())) + unsafe { + let obj = T::from_handle(self.handle.clone()); + let result = f(context, &obj); + let _ = obj.forget_into_handle(); + result + } } else { default(context) } @@ -157,11 +163,7 @@ where { #[allow(clippy::redundant_clone)] // the clone is not redundant fn clone(&self) -> Self { - if self.is_some() { - Self::some(T::from_handle(self.handle.clone()).clone()) - } else { - Self::none() - } + self.map_ref_or_else((), |()| Self::none(), |(), obj| Self::some(obj.clone())) } } @@ -177,7 +179,10 @@ where return true; } if self.is_some() && other.is_some() { - return T::from_handle(self.handle.clone()) == T::from_handle(other.handle.clone()); + unsafe { + return ManagedRef::<'_, _, T>::wrap_handle(self.handle.clone()) + == ManagedRef::<'_, _, T>::wrap_handle(other.handle.clone()); + } } false } @@ -199,19 +204,18 @@ where const SKIPS_RESERIALIZATION: bool = false; type Ref<'a> = Self; - fn from_byte_reader(reader: Reader) -> Self { - let handle = T::OwnHandle::from_byte_reader(reader); + 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 from_byte_reader_as_borrow<'a, Reader: FnMut(&mut [u8])>( - reader: Reader, - ) -> Self::Ref<'a> { - Self::from_byte_reader(reader) + unsafe fn borrow_from_payload<'a>(payload: &Self::PAYLOAD) -> Self::Ref<'a> { + // TODO: managed ref + Self::read_from_payload(payload) } - fn into_byte_writer R>(self, writer: Writer) -> R { - ::into_byte_writer(self.handle, writer) + fn save_to_payload(self, payload: &mut Self::PAYLOAD) { + self.handle.get_raw_handle().save_to_payload(payload); } } @@ -325,12 +329,10 @@ where T: ManagedType + core::fmt::Debug, { fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { - if self.is_some() { - f.debug_tuple("ManagedOption::Some") - .field(&T::from_handle(self.handle.clone())) - .finish() - } else { - f.write_str("ManagedOption::None") - } + self.map_ref_or_else( + f, + |f| f.write_str("ManagedOption::None"), + |f, obj| f.debug_tuple("ManagedOption::Some").field(obj).finish(), + ) } } diff --git a/framework/base/src/types/managed/wrapped/managed_ref.rs b/framework/base/src/types/managed/wrapped/managed_ref.rs index 143d79e1d4..bd737f358e 100644 --- a/framework/base/src/types/managed/wrapped/managed_ref.rs +++ b/framework/base/src/types/managed/wrapped/managed_ref.rs @@ -34,7 +34,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, @@ -49,7 +49,7 @@ where } } -impl<'a, M, T> ManagedRef<'a, M, T> +impl ManagedRef<'_, M, T> where M: ManagedTypeApi, T: ManagedType + Clone, @@ -60,13 +60,13 @@ where } } -impl<'a, M, T> Clone for ManagedRef<'a, M, T> +impl ManagedRef<'_, 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, @@ -75,7 +75,7 @@ where } } -impl<'a, M, T> Deref for ManagedRef<'a, M, T> +impl Deref for ManagedRef<'_, M, T> where M: ManagedTypeApi, T: ManagedType, @@ -88,7 +88,7 @@ where } } -impl<'a, M, T> Borrow for ManagedRef<'a, M, T> +impl Borrow for ManagedRef<'_, M, T> where M: ManagedTypeApi, T: ManagedType, @@ -110,7 +110,7 @@ where } } -impl<'a, M, T> PartialEq for ManagedRef<'a, M, T> +impl PartialEq for ManagedRef<'_, M, T> where M: ManagedTypeApi, T: ManagedType + PartialEq, @@ -121,14 +121,14 @@ where } } -impl<'a, M, T> Eq for ManagedRef<'a, M, T> +impl Eq for ManagedRef<'_, M, T> where M: ManagedTypeApi, T: ManagedType + PartialEq, { } -impl<'a, M, T> TopEncode for ManagedRef<'a, M, T> +impl TopEncode for ManagedRef<'_, M, T> where M: ManagedTypeApi, T: ManagedType + TopEncode, @@ -143,7 +143,7 @@ where } } -impl<'a, M, T> NestedEncode for ManagedRef<'a, M, T> +impl NestedEncode for ManagedRef<'_, M, T> where M: ManagedTypeApi, T: ManagedType + NestedEncode, @@ -158,7 +158,7 @@ where } } -impl<'a, M, T> core::fmt::Debug for ManagedRef<'a, M, T> +impl core::fmt::Debug for ManagedRef<'_, M, T> where M: ManagedTypeApi, T: ManagedType + core::fmt::Debug, diff --git a/framework/base/src/types/managed/wrapped/managed_ref_mut.rs b/framework/base/src/types/managed/wrapped/managed_ref_mut.rs new file mode 100644 index 0000000000..e017021d24 --- /dev/null +++ b/framework/base/src/types/managed/wrapped/managed_ref_mut.rs @@ -0,0 +1,174 @@ +use core::ops::DerefMut; +use core::{borrow::Borrow, marker::PhantomData, ops::Deref}; + +use crate::codec::{ + EncodeErrorHandler, NestedEncode, NestedEncodeOutput, TopEncode, TopEncodeOutput, +}; + +use crate::{api::ManagedTypeApi, types::ManagedType}; + +/// A very efficient mutable reference to a managed type. +/// +/// It can be dereferenced mutably (DerefMut). +pub struct ManagedRefMut<'a, M, T> +where + M: ManagedTypeApi, + T: ManagedType, +{ + pub(super) _phantom_m: PhantomData, + pub(super) _phantom_t: PhantomData<&'a mut T>, + pub(super) handle: T::OwnHandle, +} + +impl ManagedRefMut<'_, M, T> +where + M: ManagedTypeApi, + T: ManagedType, +{ + pub fn new(value: &mut T) -> Self { + Self { + _phantom_m: PhantomData, + _phantom_t: PhantomData, + handle: value.get_handle(), + } + } + + /// Will completely disregard lifetimes, use with care. + #[doc(hidden)] + pub(crate) unsafe fn wrap_handle(handle: T::OwnHandle) -> Self { + Self { + _phantom_m: PhantomData, + _phantom_t: PhantomData, + handle, + } + } +} + +impl ManagedRefMut<'_, M, T> +where + M: ManagedTypeApi, + T: ManagedType + Clone, +{ + /// Syntactic sugar for dereferencing and cloning the object. + pub fn clone_value(&self) -> T { + self.deref().clone() + } +} + +impl Clone for ManagedRefMut<'_, M, T> +where + M: ManagedTypeApi, + T: ManagedType, +{ + #[inline] + fn clone(&self) -> Self { + Self { + _phantom_m: PhantomData, + _phantom_t: PhantomData, + handle: self.handle.clone(), + } + } +} + +impl Deref for ManagedRefMut<'_, M, T> +where + M: ManagedTypeApi, + T: ManagedType, +{ + type Target = T; + + #[inline] + fn deref(&self) -> &Self::Target { + Self::Target::transmute_from_handle_ref(&self.handle) + } +} + +impl DerefMut for ManagedRefMut<'_, M, T> +where + M: ManagedTypeApi, + T: ManagedType, +{ + fn deref_mut(&mut self) -> &mut Self::Target { + Self::Target::transmute_from_handle_ref_mut(&mut self.handle) + } +} + +impl Borrow for ManagedRefMut<'_, M, T> +where + M: ManagedTypeApi, + T: ManagedType, +{ + #[inline] + fn borrow(&self) -> &T { + self.deref() + } +} + +impl<'a, M, T> From<&'a mut T> for ManagedRefMut<'a, M, T> +where + M: ManagedTypeApi, + T: ManagedType, +{ + #[inline] + fn from(value_ref: &'a mut T) -> Self { + Self::new(value_ref) + } +} + +impl PartialEq for ManagedRefMut<'_, M, T> +where + M: ManagedTypeApi, + T: ManagedType + PartialEq, +{ + #[inline] + fn eq(&self, other: &Self) -> bool { + self.deref() == other.deref() + } +} + +impl Eq for ManagedRefMut<'_, M, T> +where + M: ManagedTypeApi, + T: ManagedType + PartialEq, +{ +} + +impl TopEncode for ManagedRefMut<'_, M, T> +where + M: ManagedTypeApi, + T: ManagedType + TopEncode, +{ + #[inline] + fn top_encode_or_handle_err(&self, output: O, h: H) -> Result<(), H::HandledErr> + where + O: TopEncodeOutput, + H: EncodeErrorHandler, + { + self.deref().top_encode_or_handle_err(output, h) + } +} + +impl NestedEncode for ManagedRefMut<'_, M, T> +where + M: ManagedTypeApi, + T: ManagedType + NestedEncode, +{ + #[inline] + fn dep_encode_or_handle_err(&self, dest: &mut O, h: H) -> Result<(), H::HandledErr> + where + O: NestedEncodeOutput, + H: EncodeErrorHandler, + { + self.deref().dep_encode_or_handle_err(dest, h) + } +} + +impl core::fmt::Debug for ManagedRefMut<'_, M, T> +where + M: ManagedTypeApi, + T: ManagedType + core::fmt::Debug, +{ + fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { + f.debug_tuple("ManagedRefMut").field(self.deref()).finish() + } +} diff --git a/framework/base/src/types/managed/wrapped/managed_vec.rs b/framework/base/src/types/managed/wrapped/managed_vec.rs index 5cf35be4b6..ebb0f0d157 100644 --- a/framework/base/src/types/managed/wrapped/managed_vec.rs +++ b/framework/base/src/types/managed/wrapped/managed_vec.rs @@ -1,4 +1,4 @@ -use super::EncodedManagedVecItem; +use super::{EncodedManagedVecItem, ManagedVecItemPayload}; use crate::{ abi::{TypeAbi, TypeAbiFrom, TypeDescriptionContainer, TypeName}, api::{ErrorApiImpl, InvalidSliceError, ManagedTypeApi}, @@ -8,8 +8,8 @@ use crate::{ TopEncodeMultiOutput, TopEncodeOutput, }, types::{ - ManagedBuffer, ManagedBufferNestedDecodeInput, ManagedType, ManagedVecItem, ManagedVecRef, - ManagedVecRefIterator, MultiValueEncoded, MultiValueManagedVec, + ManagedBuffer, ManagedBufferNestedDecodeInput, ManagedType, ManagedVecItem, + ManagedVecRefIterator, ManagedVecRefMut, MultiValueEncoded, MultiValueManagedVec, }, }; use alloc::{format, vec::Vec}; @@ -45,7 +45,7 @@ where type OwnHandle = M::ManagedBufferHandle; #[inline] - fn from_handle(handle: M::ManagedBufferHandle) -> Self { + unsafe fn from_handle(handle: M::ManagedBufferHandle) -> Self { ManagedVec { buffer: ManagedBuffer::from_handle(handle), _phantom: PhantomData, @@ -56,9 +56,17 @@ where self.buffer.get_handle() } + unsafe fn forget_into_handle(self) -> Self::OwnHandle { + self.buffer.forget_into_handle() + } + fn transmute_from_handle_ref(handle_ref: &M::ManagedBufferHandle) -> &Self { unsafe { core::mem::transmute(handle_ref) } } + + fn transmute_from_handle_ref_mut(handle_ref: &mut M::ManagedBufferHandle) -> &mut Self { + unsafe { core::mem::transmute(handle_ref) } + } } impl ManagedVec @@ -133,15 +141,16 @@ where pub fn try_get(&self, index: usize) -> Option> { let byte_index = index * T::payload_size(); - let mut load_result = Ok(()); - let result = unsafe { - T::from_byte_reader_as_borrow(|dest_slice| { - load_result = self.buffer.load_slice(byte_index, dest_slice); - }) - }; - match load_result { - Ok(_) => Some(result), - Err(_) => None, + + let mut payload = T::PAYLOAD::new_buffer(); + if self + .buffer + .load_slice(byte_index, payload.payload_slice_mut()) + .is_ok() + { + unsafe { Some(T::borrow_from_payload(&payload)) } + } else { + None } } @@ -173,26 +182,28 @@ where } } - pub fn get_mut(&mut self, index: usize) -> ManagedVecRef { - ManagedVecRef::new(self.get_handle(), index) + pub fn get_mut(&mut self, index: usize) -> ManagedVecRefMut { + ManagedVecRefMut::new(self.get_handle(), index) } pub(super) unsafe fn get_unsafe(&self, index: usize) -> T { let byte_index = index * T::payload_size(); - let mut load_result = Ok(()); - let result = T::from_byte_reader(|dest_slice| { - load_result = self.buffer.load_slice(byte_index, dest_slice); - }); - - match load_result { - Ok(_) => result, - Err(_) => M::error_api_impl().signal_error(INDEX_OUT_OF_RANGE_MSG), + let mut payload = T::PAYLOAD::new_buffer(); + if self + .buffer + .load_slice(byte_index, payload.payload_slice_mut()) + .is_err() + { + M::error_api_impl().signal_error(INDEX_OUT_OF_RANGE_MSG); } + T::read_from_payload(&payload) } pub fn set(&mut self, index: usize, item: T) -> Result<(), InvalidSliceError> { let byte_index = index * T::payload_size(); - item.into_byte_writer(|slice| self.buffer.set_slice(byte_index, slice)) + let mut payload = T::PAYLOAD::new_buffer(); + item.save_to_payload(&mut payload); + self.buffer.set_slice(byte_index, payload.payload_slice()) } /// Returns a new `ManagedVec`, containing the [start_index, end_index) range of elements. @@ -205,9 +216,9 @@ where } pub fn push(&mut self, item: T) { - item.into_byte_writer(|bytes| { - self.buffer.append_bytes(bytes); - }); + let mut payload = T::PAYLOAD::new_buffer(); + item.save_to_payload(&mut payload); + self.buffer.append_bytes(payload.payload_slice()); } pub fn remove(&mut self, index: usize) { @@ -233,7 +244,7 @@ where ManagedVec::new() }; - self.buffer = part_before.buffer; + *self = part_before; self.buffer.append(&part_after.buffer); } @@ -251,9 +262,9 @@ where } pub fn overwrite_with_single_item(&mut self, item: T) { - item.into_byte_writer(|bytes| { - self.buffer.overwrite(bytes); - }); + let mut payload = T::PAYLOAD::new_buffer(); + item.save_to_payload(&mut payload); + self.buffer.overwrite(payload.payload_slice()); } /// Appends all the contents of another managed vec at the end of the current one. @@ -510,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 } @@ -533,12 +544,16 @@ where } let mut byte_index = 0; while byte_index < self_len { - let self_item = T::from_byte_reader(|dest_slice| { - let _ = self.buffer.load_slice(byte_index, dest_slice); - }); - let other_item = T::from_byte_reader(|dest_slice| { - let _ = other.buffer.load_slice(byte_index, dest_slice); - }); + let mut self_payload = T::PAYLOAD::new_buffer(); + let _ = self + .buffer + .load_slice(byte_index, self_payload.payload_slice_mut()); + let mut other_payload = T::PAYLOAD::new_buffer(); + let _ = 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; } @@ -596,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(()) @@ -616,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(()) } @@ -733,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_item.rs b/framework/base/src/types/managed/wrapped/managed_vec_item.rs index 9c85a1d713..62e62ad4dd 100644 --- a/framework/base/src/types/managed/wrapped/managed_vec_item.rs +++ b/framework/base/src/types/managed/wrapped/managed_vec_item.rs @@ -4,14 +4,17 @@ use multiversx_chain_core::types::{EsdtLocalRole, EsdtTokenType}; use multiversx_sc_codec::multi_types::{MultiValue2, MultiValue3}; use crate::{ - api::ManagedTypeApi, + api::{use_raw_handle, HandleConstraints, ManagedTypeApi}, types::{ BigInt, BigUint, EllipticCurve, ManagedAddress, ManagedBuffer, ManagedByteArray, ManagedRef, ManagedType, ManagedVec, TokenIdentifier, }, }; -use super::{ManagedVecItemNestedTuple, ManagedVecItemPayload, ManagedVecItemPayloadBuffer}; +use super::{ + ManagedVecItemNestedTuple, ManagedVecItemPayload, ManagedVecItemPayloadAdd, + ManagedVecItemPayloadBuffer, ManagedVecRef, +}; /// Types that implement this trait can be items inside a `ManagedVec`. /// All these types need a payload, i.e a representation that gets stored @@ -43,27 +46,53 @@ pub trait ManagedVecItem: 'static { } /// Parses given bytes as a an owned object. - fn from_byte_reader(reader: Reader) -> Self; + fn read_from_payload(payload: &Self::PAYLOAD) -> Self; /// Parses given bytes as a representation of the object, either owned, or a reference. /// /// # Safety /// /// In certain cases this involves practically disregarding the lifetimes, hence it is unsafe. - unsafe fn from_byte_reader_as_borrow<'a, Reader: FnMut(&mut [u8])>( - reader: Reader, - ) -> Self::Ref<'a>; + unsafe fn borrow_from_payload<'a>(payload: &Self::PAYLOAD) -> Self::Ref<'a>; /// Converts the object into bytes. /// - /// The output is processed by the `writer` lambda. - /// The writer is provided by the caller. - /// The callee will use it to pass on the bytes. - /// /// The method is used when instering (push, overwrite) into a ManagedVec. /// /// Note that a destructor should not be called at this moment, since the ManagedVec will take ownership of the item. - fn into_byte_writer R>(self, writer: Writer) -> R; + fn save_to_payload(self, payload: &mut Self::PAYLOAD); +} + +/// Used by the ManagedVecItem derive. +/// +/// ## Safety +/// +/// Only works correctly if the given index is correct, otherwise undefined behavior is possible. +pub unsafe fn managed_vec_item_read_from_payload_index(payload: &P, index: &mut usize) -> T +where + T: ManagedVecItem, + P: ManagedVecItemPayload, +{ + let value = T::read_from_payload(payload.slice_unchecked(*index)); + *index += T::PAYLOAD::payload_size(); + value +} + +/// Used by the ManagedVecItem derive. +/// +/// ## Safety +/// +/// Only works correctly if the given index is correct, otherwise undefined behavior is possible. +pub unsafe fn managed_vec_item_save_to_payload_index( + item: T, + payload: &mut P, + index: &mut usize, +) where + T: ManagedVecItem, + P: ManagedVecItemPayload, +{ + item.save_to_payload(payload.slice_unchecked_mut(*index)); + *index += T::PAYLOAD::payload_size(); } macro_rules! impl_int { @@ -72,20 +101,17 @@ macro_rules! impl_int { type PAYLOAD = ManagedVecItemPayloadBuffer<$payload_size>; const SKIPS_RESERIALIZATION: bool = true; type Ref<'a> = Self; - fn from_byte_reader(mut reader: Reader) -> Self { - let mut arr: [u8; $payload_size] = [0u8; $payload_size]; - reader(&mut arr[..]); - $ty::from_be_bytes(arr) + + fn read_from_payload(payload: &Self::PAYLOAD) -> Self { + $ty::from_be_bytes(payload.buffer) } - unsafe fn from_byte_reader_as_borrow<'a, Reader: FnMut(&mut [u8])>( - reader: Reader, - ) -> Self::Ref<'a> { - Self::from_byte_reader(reader) + + unsafe fn borrow_from_payload<'a>(payload: &Self::PAYLOAD) -> Self::Ref<'a> { + $ty::from_be_bytes(payload.buffer) } - fn into_byte_writer R>(self, mut writer: Writer) -> R { - let bytes = self.to_be_bytes(); - writer(&bytes) + fn save_to_payload(self, payload: &mut Self::PAYLOAD) { + payload.buffer = self.to_be_bytes(); } } }; @@ -102,21 +128,16 @@ impl ManagedVecItem for usize { const SKIPS_RESERIALIZATION: bool = true; type Ref<'a> = Self; - fn from_byte_reader(mut reader: Reader) -> Self { - let mut arr: [u8; 4] = [0u8; 4]; - reader(&mut arr[..]); - u32::from_be_bytes(arr) as usize + fn read_from_payload(payload: &Self::PAYLOAD) -> Self { + u32::read_from_payload(payload) as usize } - unsafe fn from_byte_reader_as_borrow<'a, Reader: FnMut(&mut [u8])>( - reader: Reader, - ) -> Self::Ref<'a> { - Self::from_byte_reader(reader) + unsafe fn borrow_from_payload<'a>(payload: &Self::PAYLOAD) -> Self::Ref<'a> { + Self::read_from_payload(payload) } - fn into_byte_writer R>(self, mut writer: Writer) -> R { - let bytes = (self as u32).to_be_bytes(); - writer(&bytes) + fn save_to_payload(self, payload: &mut Self::PAYLOAD) { + (self as u32).save_to_payload(payload); } } @@ -125,62 +146,56 @@ impl ManagedVecItem for bool { const SKIPS_RESERIALIZATION: bool = true; type Ref<'a> = Self; - fn from_byte_reader(reader: Reader) -> Self { - u8::from_byte_reader(reader) > 0 + fn read_from_payload(payload: &Self::PAYLOAD) -> Self { + u8::read_from_payload(payload) > 0 } - unsafe fn from_byte_reader_as_borrow<'a, Reader: FnMut(&mut [u8])>( - reader: Reader, - ) -> Self::Ref<'a> { - Self::from_byte_reader(reader) + unsafe fn borrow_from_payload<'a>(payload: &Self::PAYLOAD) -> Self::Ref<'a> { + Self::read_from_payload(payload) } - fn into_byte_writer R>(self, writer: Writer) -> R { + fn save_to_payload(self, payload: &mut Self::PAYLOAD) { // true -> 1u8 // false -> 0u8 - let u8_value = u8::from(self); - ::into_byte_writer(u8_value, writer) + u8::from(self).save_to_payload(payload); } } impl ManagedVecItem for Option where - (u8, (T, ())): ManagedVecItemNestedTuple, + ManagedVecItemPayloadBuffer<1>: ManagedVecItemPayloadAdd, T: ManagedVecItem, { - type PAYLOAD = <(u8, (T, ())) as ManagedVecItemNestedTuple>::PAYLOAD; + type PAYLOAD = as ManagedVecItemPayloadAdd>::Output; const SKIPS_RESERIALIZATION: bool = false; - type Ref<'a> = Self; + type Ref<'a> = ManagedVecRef<'a, Self>; - fn from_byte_reader(mut reader: Reader) -> Self { - let mut payload = Self::PAYLOAD::new_buffer(); - let payload_slice = payload.payload_slice_mut(); - reader(payload_slice); - if payload_slice[0] == 0 { + 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); + if disc == 0 { None } else { - Some(T::from_byte_reader(|bytes| { - bytes.copy_from_slice(&payload_slice[1..]); - })) + Some(T::read_from_payload(p2)) } } - unsafe fn from_byte_reader_as_borrow<'a, Reader: FnMut(&mut [u8])>( - reader: Reader, - ) -> Self::Ref<'a> { - Self::from_byte_reader(reader) + unsafe fn borrow_from_payload<'a>(payload: &Self::PAYLOAD) -> Self::Ref<'a> { + ManagedVecRef::new(Self::read_from_payload(payload)) } - fn into_byte_writer R>(self, mut writer: Writer) -> R { - let mut payload = Self::PAYLOAD::new_buffer(); - let slice = payload.payload_slice_mut(); + fn save_to_payload(self, payload: &mut Self::PAYLOAD) { + let (p1, p2) = as ManagedVecItemPayloadAdd< + T::PAYLOAD, + >>::split_mut_from_add(payload); + if let Some(t) = self { - slice[0] = 1; - T::into_byte_writer(t, |bytes| { - slice[1..].copy_from_slice(bytes); - }); + 1u8.save_to_payload(p1); + t.save_to_payload(p2); } - writer(slice) } } @@ -191,20 +206,19 @@ macro_rules! impl_managed_type { const SKIPS_RESERIALIZATION: bool = false; type Ref<'a> = ManagedRef<'a, M, Self>; - fn from_byte_reader(reader: Reader) -> Self { - let handle = <$ty as ManagedType>::OwnHandle::from_byte_reader(reader); - $ty::from_handle(handle) + fn read_from_payload(payload: &Self::PAYLOAD) -> Self { + let handle = use_raw_handle(i32::read_from_payload(payload)); + unsafe { Self::from_handle(handle) } } - unsafe fn from_byte_reader_as_borrow<'a, Reader: FnMut(&mut [u8])>( - reader: Reader, - ) -> Self::Ref<'a> { - let handle = <$ty as ManagedType>::OwnHandle::from_byte_reader(reader); + unsafe fn borrow_from_payload<'a>(payload: &Self::PAYLOAD) -> Self::Ref<'a> { + let handle = use_raw_handle(i32::read_from_payload(payload)); ManagedRef::wrap_handle(handle) } - fn into_byte_writer R>(self, writer: Writer) -> R { - <$ty as ManagedType>::OwnHandle::into_byte_writer(self.get_handle(), writer) + fn save_to_payload(self, payload: &mut Self::PAYLOAD) { + let handle = unsafe { self.forget_into_handle() }; + handle.get_raw_handle().save_to_payload(payload); } } }; @@ -225,23 +239,19 @@ where const SKIPS_RESERIALIZATION: bool = false; type Ref<'a> = ManagedRef<'a, M, Self>; - fn from_byte_reader(reader: Reader) -> Self { - let handle = >::OwnHandle::from_byte_reader(reader); - Self::from_handle(handle) + fn read_from_payload(payload: &Self::PAYLOAD) -> Self { + let handle = use_raw_handle(i32::read_from_payload(payload)); + unsafe { Self::from_handle(handle) } } - unsafe fn from_byte_reader_as_borrow<'a, Reader: FnMut(&mut [u8])>( - reader: Reader, - ) -> Self::Ref<'a> { - let handle = >::OwnHandle::from_byte_reader(reader); + unsafe fn borrow_from_payload<'a>(payload: &Self::PAYLOAD) -> Self::Ref<'a> { + let handle = use_raw_handle(i32::read_from_payload(payload)); ManagedRef::wrap_handle(handle) } - fn into_byte_writer R>(self, writer: Writer) -> R { - <>::OwnHandle as ManagedVecItem>::into_byte_writer( - self.get_handle(), - writer, - ) + fn save_to_payload(self, payload: &mut Self::PAYLOAD) { + let handle = unsafe { self.forget_into_handle() }; + handle.get_raw_handle().save_to_payload(payload); } } @@ -254,20 +264,19 @@ where const SKIPS_RESERIALIZATION: bool = false; type Ref<'a> = ManagedRef<'a, M, Self>; - fn from_byte_reader(reader: Reader) -> Self { - let handle = M::ManagedBufferHandle::from_byte_reader(reader); - Self::from_handle(handle) + fn read_from_payload(payload: &Self::PAYLOAD) -> Self { + let handle = use_raw_handle(i32::read_from_payload(payload)); + unsafe { Self::from_handle(handle) } } - unsafe fn from_byte_reader_as_borrow<'a, Reader: FnMut(&mut [u8])>( - reader: Reader, - ) -> Self::Ref<'a> { - let handle = M::ManagedBufferHandle::from_byte_reader(reader); + unsafe fn borrow_from_payload<'a>(payload: &Self::PAYLOAD) -> Self::Ref<'a> { + let handle = use_raw_handle(i32::read_from_payload(payload)); ManagedRef::wrap_handle(handle) } - fn into_byte_writer R>(self, writer: Writer) -> R { - ::into_byte_writer(self.get_handle(), writer) + fn save_to_payload(self, payload: &mut Self::PAYLOAD) { + let handle = unsafe { self.forget_into_handle() }; + handle.get_raw_handle().save_to_payload(payload); } } @@ -276,40 +285,34 @@ impl ManagedVecItem for EsdtTokenType { const SKIPS_RESERIALIZATION: bool = true; type Ref<'a> = Self; - fn from_byte_reader(mut reader: Reader) -> Self { - let mut arr: [u8; 1] = [0u8; 1]; - reader(&mut arr[..]); - arr[0].into() + fn read_from_payload(payload: &Self::PAYLOAD) -> Self { + u8::read_from_payload(payload).into() } - unsafe fn from_byte_reader_as_borrow<'a, Reader: FnMut(&mut [u8])>( - reader: Reader, - ) -> Self::Ref<'a> { - Self::from_byte_reader(reader) + unsafe fn borrow_from_payload<'a>(payload: &Self::PAYLOAD) -> Self::Ref<'a> { + Self::read_from_payload(payload) } - fn into_byte_writer R>(self, mut writer: Writer) -> R { - writer(&[self.as_u8()]) + fn save_to_payload(self, payload: &mut Self::PAYLOAD) { + self.as_u8().save_to_payload(payload); } } impl ManagedVecItem for EsdtLocalRole { - type PAYLOAD = ManagedVecItemPayloadBuffer<1>; + type PAYLOAD = ManagedVecItemPayloadBuffer<2>; const SKIPS_RESERIALIZATION: bool = false; // TODO: might be ok to be true, but needs testing type Ref<'a> = Self; - fn from_byte_reader(reader: Reader) -> Self { - u16::from_byte_reader(reader).into() + fn read_from_payload(payload: &Self::PAYLOAD) -> Self { + u16::read_from_payload(payload).into() } - unsafe fn from_byte_reader_as_borrow<'a, Reader: FnMut(&mut [u8])>( - reader: Reader, - ) -> Self::Ref<'a> { - Self::from_byte_reader(reader) + unsafe fn borrow_from_payload<'a>(payload: &Self::PAYLOAD) -> Self::Ref<'a> { + Self::read_from_payload(payload) } - fn into_byte_writer R>(self, writer: Writer) -> R { - ::into_byte_writer(self.as_u16(), writer) + fn save_to_payload(self, payload: &mut Self::PAYLOAD) { + self.as_u16().save_to_payload(payload); } } @@ -321,51 +324,31 @@ 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 from_byte_reader(mut reader: Reader) -> Self { - let mut payload = ::new_buffer(); - let payload_slice = ManagedVecItemPayload::payload_slice_mut(&mut payload); - reader(payload_slice); + fn read_from_payload(payload: &Self::PAYLOAD) -> Self { let mut index = 0; - - ( - T1::from_byte_reader(|bytes| { - let next_index = index + T1::payload_size(); - bytes.copy_from_slice(&payload_slice[index..next_index]); - index = next_index; - }), - T2::from_byte_reader(|bytes| { - let next_index = index + T2::payload_size(); - bytes.copy_from_slice(&payload_slice[index..next_index]); - index = next_index; - }), - ) - .into() + unsafe { + ( + managed_vec_item_read_from_payload_index(payload, &mut index), + managed_vec_item_read_from_payload_index(payload, &mut index), + ) + .into() + } } - unsafe fn from_byte_reader_as_borrow<'a, Reader: FnMut(&mut [u8])>( - reader: Reader, - ) -> Self::Ref<'a> { - Self::from_byte_reader(reader) + unsafe fn borrow_from_payload<'a>(payload: &Self::PAYLOAD) -> Self::Ref<'a> { + ManagedVecRef::new(Self::read_from_payload(payload)) } - fn into_byte_writer R>(self, mut writer: Writer) -> R { - let mut payload = Self::PAYLOAD::new_buffer(); - let payload_slice = ManagedVecItemPayload::payload_slice_mut(&mut payload); + fn save_to_payload(self, payload: &mut Self::PAYLOAD) { + let tuple = self.into_tuple(); let mut index = 0; - let (t1, t2) = self.into_tuple(); - T1::into_byte_writer(t1, |bytes| { - let next_index = index + T1::payload_size(); - payload_slice[index..next_index].copy_from_slice(bytes); - index = next_index; - }); - T2::into_byte_writer(t2, |bytes| { - let next_index = index + T2::payload_size(); - payload_slice[index..next_index].copy_from_slice(bytes); - index = next_index; - }); - writer(payload_slice) + + unsafe { + managed_vec_item_save_to_payload_index(tuple.0, payload, &mut index); + managed_vec_item_save_to_payload_index(tuple.1, payload, &mut index); + } } } @@ -378,60 +361,32 @@ 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 from_byte_reader(mut reader: Reader) -> Self { - let mut payload = ::new_buffer(); - let payload_slice = ManagedVecItemPayload::payload_slice_mut(&mut payload); - reader(payload_slice); + fn read_from_payload(payload: &Self::PAYLOAD) -> Self { let mut index = 0; - - ( - T1::from_byte_reader(|bytes| { - let next_index = index + T1::payload_size(); - bytes.copy_from_slice(&payload_slice[index..next_index]); - index = next_index; - }), - T2::from_byte_reader(|bytes| { - let next_index = index + T2::payload_size(); - bytes.copy_from_slice(&payload_slice[index..next_index]); - index = next_index; - }), - T3::from_byte_reader(|bytes| { - let next_index = index + T3::payload_size(); - bytes.copy_from_slice(&payload_slice[index..next_index]); - index = next_index; - }), - ) - .into() + unsafe { + ( + managed_vec_item_read_from_payload_index(payload, &mut index), + managed_vec_item_read_from_payload_index(payload, &mut index), + managed_vec_item_read_from_payload_index(payload, &mut index), + ) + .into() + } } - unsafe fn from_byte_reader_as_borrow<'a, Reader: FnMut(&mut [u8])>( - reader: Reader, - ) -> Self::Ref<'a> { - Self::from_byte_reader(reader) + unsafe fn borrow_from_payload<'a>(payload: &Self::PAYLOAD) -> Self::Ref<'a> { + ManagedVecRef::new(Self::read_from_payload(payload)) } - fn into_byte_writer R>(self, mut writer: Writer) -> R { - let mut payload = Self::PAYLOAD::new_buffer(); - let payload_slice = ManagedVecItemPayload::payload_slice_mut(&mut payload); + fn save_to_payload(self, payload: &mut Self::PAYLOAD) { + let tuple = self.into_tuple(); let mut index = 0; - let (t1, t2, t3) = self.into_tuple(); - T1::into_byte_writer(t1, |bytes| { - let next_index = index + T1::payload_size(); - payload_slice[index..next_index].copy_from_slice(bytes); - index = next_index; - }); - T2::into_byte_writer(t2, |bytes| { - let next_index = index + T2::payload_size(); - payload_slice[index..next_index].copy_from_slice(bytes); - index = next_index; - }); - T3::into_byte_writer(t3, |bytes| { - let next_index = index + T2::payload_size(); - payload_slice[index..next_index].copy_from_slice(bytes); - index = next_index; - }); - writer(payload_slice) + + unsafe { + managed_vec_item_save_to_payload_index(tuple.0, payload, &mut index); + managed_vec_item_save_to_payload_index(tuple.1, payload, &mut index); + managed_vec_item_save_to_payload_index(tuple.2, payload, &mut index); + } } } diff --git a/framework/base/src/types/managed/wrapped/managed_vec_item_payload.rs b/framework/base/src/types/managed/wrapped/managed_vec_item_payload.rs index 07adc31a08..a3a9c58475 100644 --- a/framework/base/src/types/managed/wrapped/managed_vec_item_payload.rs +++ b/framework/base/src/types/managed/wrapped/managed_vec_item_payload.rs @@ -9,6 +9,20 @@ pub trait ManagedVecItemPayload { fn payload_slice(&self) -> &[u8]; fn payload_slice_mut(&mut self) -> &mut [u8]; + + /// Takes a sub-payload item. + /// + /// ## Safety + /// + /// Only works correctly if the given index is correct, otherwise undefined behavior is possible. + unsafe fn slice_unchecked(&self, index: usize) -> &S; + + /// Takes a sub-payload item. + /// + /// ## Safety + /// + /// Only works correctly if the given index is correct, otherwise undefined behavior is possible. + unsafe fn slice_unchecked_mut(&mut self, index: usize) -> &mut S; } /// Empty ManagedVecItem. @@ -32,11 +46,26 @@ impl ManagedVecItemPayload for ManagedVecItemEmptyPayload { fn payload_slice_mut(&mut self) -> &mut [u8] { &mut [] } + + unsafe fn slice_unchecked(&self, _index: usize) -> &S { + unimplemented!() + } + + unsafe fn slice_unchecked_mut(&mut self, _index: usize) -> &mut S { + unimplemented!() + } } /// The main ManagedVecItemPayload implementation. Uses an array in its implementation. +#[repr(transparent)] pub struct ManagedVecItemPayloadBuffer { - buffer: [u8; N], + pub buffer: [u8; N], +} + +impl From<[u8; N]> for ManagedVecItemPayloadBuffer { + fn from(value: [u8; N]) -> Self { + ManagedVecItemPayloadBuffer { buffer: value } + } } impl ManagedVecItemPayload for ManagedVecItemPayloadBuffer { @@ -55,6 +84,16 @@ impl ManagedVecItemPayload for ManagedVecItemPayloadBuffer { fn payload_slice_mut(&mut self) -> &mut [u8] { &mut self.buffer[..] } + + unsafe fn slice_unchecked(&self, index: usize) -> &S { + let ptr = self.buffer.as_ptr().add(index); + &*ptr.cast::() + } + + unsafe fn slice_unchecked_mut(&mut self, index: usize) -> &mut S { + let ptr = self.buffer.as_mut_ptr().add(index); + &mut *ptr.cast::() + } } /// Describes concatantion of smaller payloads into a larger one. @@ -67,12 +106,27 @@ where Rhs: ManagedVecItemPayload, { type Output: ManagedVecItemPayload; + + fn split_from_add(payload: &Self::Output) -> (&Self, &Rhs); + + fn split_mut_from_add(payload: &mut Self::Output) -> (&mut Self, &mut Rhs); } -impl ManagedVecItemPayloadAdd - for ManagedVecItemPayloadBuffer +impl

, +} + +impl ManagedVecPayloadIterator +where + M: ManagedTypeApi, + P: ManagedVecItemPayload, +{ + /// Unsafe because it works with the managed vec handle directly, so does not take ownership into account. + pub(crate) unsafe fn new(vec_handle: M::ManagedBufferHandle) -> Self { + let byte_end = M::managed_type_impl().mb_len(vec_handle.clone()); + ManagedVecPayloadIterator { + vec_handle, + byte_start: 0, + byte_end, + _phantom: PhantomData, + } + } + + /// Unsafe because it works with the managed vec handle directly, so does not take ownership into account. + pub(super) unsafe fn clone_iter(&self) -> Self { + ManagedVecPayloadIterator { + vec_handle: self.vec_handle.clone(), + byte_start: self.byte_start, + byte_end: self.byte_end, + _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 Iterator for ManagedVecPayloadIterator +where + M: ManagedTypeApi, + P: ManagedVecItemPayload, +{ + type Item = P; + + fn next(&mut self) -> Option

{ + 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( + self.vec_handle.clone(), + self.byte_start, + payload.payload_slice_mut(), + ); + + self.byte_start = next_byte_start; + Some(payload) + } + + fn size_hint(&self) -> (usize, Option) { + let remaining = self.remaining(); + (remaining, Some(remaining)) + } +} + +impl ExactSizeIterator for ManagedVecPayloadIterator +where + M: ManagedTypeApi, + P: ManagedVecItemPayload, +{ + fn len(&self) -> usize { + self.remaining() + } +} + +impl DoubleEndedIterator for ManagedVecPayloadIterator +where + M: ManagedTypeApi, + P: ManagedVecItemPayload, +{ + fn next_back(&mut self) -> Option { + if self.iter_is_empty() { + return None; + } + self.byte_end -= P::payload_size(); + + let mut payload = P::new_buffer(); + let _ = M::managed_type_impl().mb_load_slice( + self.vec_handle.clone(), + self.byte_end, + payload.payload_slice_mut(), + ); + + Some(payload) + } +} 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 new file mode 100644 index 0000000000..f48e3ecab1 --- /dev/null +++ b/framework/base/src/types/managed/wrapped/managed_vec_iter_ref.rs @@ -0,0 +1,126 @@ +use core::marker::PhantomData; + +use multiversx_sc_codec::{DecodeError, DecodeErrorHandler, TopDecodeMultiInput}; + +use crate::{ + api::{ErrorApi, ManagedTypeApi}, + types::{ManagedBuffer, ManagedType}, +}; + +use super::{ManagedVec, ManagedVecItem, ManagedVecPayloadIterator}; + +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, + T: ManagedVecItem, +{ + payload_iter: ManagedVecPayloadIterator, + _phantom: PhantomData<&'a ManagedVec>, +} + +impl<'a, M, T> ManagedVecRefIterator<'a, M, T> +where + M: ManagedTypeApi, + T: ManagedVecItem, +{ + pub(crate) unsafe fn new_from_handle(vec_handle: M::ManagedBufferHandle) -> Self { + unsafe { + ManagedVecRefIterator { + payload_iter: ManagedVecPayloadIterator::new(vec_handle), + _phantom: PhantomData, + } + } + } + + pub(crate) fn new(managed_vec: &'a ManagedVec) -> Self { + unsafe { ManagedVecRefIterator::new_from_handle(managed_vec.get_handle()) } + } + + pub(crate) fn iter_is_empty(&self) -> bool { + self.payload_iter.iter_is_empty() + } +} + +impl<'a, M, T> Iterator for ManagedVecRefIterator<'a, M, T> +where + M: ManagedTypeApi, + T: ManagedVecItem, +{ + type Item = T::Ref<'a>; + + fn next(&mut self) -> Option { + let payload = self.payload_iter.next()?; + unsafe { Some(T::borrow_from_payload(&payload)) } + } + + fn size_hint(&self) -> (usize, Option) { + self.payload_iter.size_hint() + } +} + +impl ExactSizeIterator for ManagedVecRefIterator<'_, M, T> +where + M: ManagedTypeApi, + T: ManagedVecItem, +{ +} + +impl DoubleEndedIterator for ManagedVecRefIterator<'_, M, T> +where + M: ManagedTypeApi, + T: ManagedVecItem, +{ + fn next_back(&mut self) -> Option { + let payload = self.payload_iter.next_back()?; + unsafe { Some(T::borrow_from_payload(&payload)) } + } +} + +impl Clone for ManagedVecRefIterator<'_, M, T> +where + M: ManagedTypeApi, + T: ManagedVecItem, +{ + fn clone(&self) -> Self { + unsafe { + ManagedVecRefIterator { + payload_iter: self.payload_iter.clone_iter(), + _phantom: PhantomData, + } + } + } +} + +impl TopDecodeMultiInput for ManagedVecRefIterator<'_, A, ManagedBuffer> +where + A: ManagedTypeApi + ErrorApi, +{ + type ValueInput = ManagedBuffer; + + fn has_next(&self) -> bool { + !self.iter_is_empty() + } + + fn next_value_input(&mut self, h: H) -> Result + where + H: DecodeErrorHandler, + { + if let Some(buffer) = self.next() { + Ok(buffer.clone()) + } else { + Err(h.handle_error(DecodeError::MULTI_TOO_FEW_ARGS)) + } + } +} 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 deleted file mode 100644 index 20942e70d4..0000000000 --- a/framework/base/src/types/managed/wrapped/managed_vec_owned_iter.rs +++ /dev/null @@ -1,115 +0,0 @@ -use crate::api::ManagedTypeApi; - -use super::{ManagedVec, ManagedVecItem}; - -impl<'a, M, T> IntoIterator for &'a ManagedVec -where - M: ManagedTypeApi, - T: ManagedVecItem, -{ - type Item = T; - type IntoIter = ManagedVecOwnedIterator<'a, M, T>; - fn into_iter(self) -> Self::IntoIter { - ManagedVecOwnedIterator::new(self) - } -} - -pub struct ManagedVecOwnedIterator<'a, M, T> -where - M: ManagedTypeApi, - T: ManagedVecItem, -{ - managed_vec: &'a ManagedVec, - byte_start: usize, - byte_end: usize, -} - -impl<'a, M, T> ManagedVecOwnedIterator<'a, M, T> -where - M: ManagedTypeApi, - T: ManagedVecItem, -{ - pub(crate) fn new(managed_vec: &'a ManagedVec) -> Self { - let byte_end = managed_vec.byte_len(); - ManagedVecOwnedIterator { - managed_vec, - byte_start: 0, - byte_end, - } - } -} - -impl<'a, M, T> Iterator for ManagedVecOwnedIterator<'a, M, T> -where - M: ManagedTypeApi, - T: ManagedVecItem, -{ - type Item = T; - - fn next(&mut self) -> Option { - // managedrev / reference type - let next_byte_start = self.byte_start + T::payload_size(); - if next_byte_start > self.byte_end { - return None; - } - let result = T::from_byte_reader(|dest_slice| { - let _ = self - .managed_vec - .buffer - .load_slice(self.byte_start, dest_slice); - }); - - self.byte_start = next_byte_start; - Some(result) - } - - fn size_hint(&self) -> (usize, Option) { - let size = T::payload_size(); - let remaining = (self.byte_end - self.byte_start) / size; - (remaining, Some(remaining)) - } -} - -impl<'a, M, T> ExactSizeIterator for ManagedVecOwnedIterator<'a, M, T> -where - M: ManagedTypeApi, - T: ManagedVecItem, -{ -} - -impl<'a, M, T> DoubleEndedIterator for ManagedVecOwnedIterator<'a, M, T> -where - M: ManagedTypeApi, - T: ManagedVecItem, -{ - fn next_back(&mut self) -> Option { - if self.byte_start + T::payload_size() > self.byte_end { - return None; - } - self.byte_end -= T::payload_size(); - - let result = T::from_byte_reader(|dest_slice| { - let _ = self - .managed_vec - .buffer - .load_slice(self.byte_end, dest_slice); - }); - - Some(result) - } -} - -impl<'a, M, T> Clone for ManagedVecOwnedIterator<'a, M, T> -where - M: ManagedTypeApi, - T: ManagedVecItem, -{ - fn clone(&self) -> Self { - let byte_end = self.byte_end; - Self { - managed_vec: self.managed_vec, - 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 b69a124668..de78fd5e6f 100644 --- a/framework/base/src/types/managed/wrapped/managed_vec_ref.rs +++ b/framework/base/src/types/managed/wrapped/managed_vec_ref.rs @@ -1,63 +1,45 @@ -use crate::{ - api::ManagedTypeApi, - types::{ManagedType, ManagedVec, ManagedVecItem}, -}; -use core::{ - marker::PhantomData, - mem::ManuallyDrop, - ops::{Deref, DerefMut}, -}; +use crate::types::ManagedVecItem; +use core::{borrow::Borrow, marker::PhantomData, mem::ManuallyDrop, ops::Deref}; -pub struct ManagedVecRef<'a, M, T> +pub struct ManagedVecRef<'a, T> where - M: ManagedTypeApi, T: ManagedVecItem, { - _phantom_m: PhantomData, - _phantom_t: PhantomData<&'a mut T>, // needed for the lifetime, even though T is present - managed_vec_handle: M::ManagedBufferHandle, - item_index: usize, + _phantom: PhantomData<&'a T>, // needed for the lifetime, even though T is present item: ManuallyDrop, } -impl<'a, M, T> ManagedVecRef<'a, M, T> +impl ManagedVecRef<'_, T> where - M: ManagedTypeApi, T: ManagedVecItem, { - #[inline] - fn wrap_as_managed_vec(managed_vec_handle: M::ManagedBufferHandle) -> ManagedVec { - ManagedVec::from_handle(managed_vec_handle) - } - - pub(super) fn new(managed_vec_handle: M::ManagedBufferHandle, item_index: usize) -> Self { - let item = - unsafe { Self::wrap_as_managed_vec(managed_vec_handle.clone()).get_unsafe(item_index) }; - Self { - _phantom_m: PhantomData, - _phantom_t: PhantomData, - managed_vec_handle, - item_index, + /// 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, item: ManuallyDrop::new(item), } } } -impl<'a, M, T> Drop for ManagedVecRef<'a, M, T> +impl Drop for ManagedVecRef<'_, T> where - M: ManagedTypeApi, T: ManagedVecItem, { fn drop(&mut self) { - let item = unsafe { ManuallyDrop::take(&mut self.item) }; - let _ = - Self::wrap_as_managed_vec(self.managed_vec_handle.clone()).set(self.item_index, item); + // TODO: improve + unsafe { + ManuallyDrop::drop(&mut self.item); + } } } -impl<'a, M, T> Deref for ManagedVecRef<'a, M, T> +impl Deref for ManagedVecRef<'_, T> where - M: ManagedTypeApi, T: ManagedVecItem, { type Target = T; @@ -67,12 +49,11 @@ where } } -impl<'a, M, T> DerefMut for ManagedVecRef<'a, M, T> +impl Borrow for ManagedVecRef<'_, T> where - M: ManagedTypeApi, T: ManagedVecItem, { - fn deref_mut(&mut self) -> &mut Self::Target { - &mut self.item + fn borrow(&self) -> &T { + self.deref() } } 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 deleted file mode 100644 index ad04b5eaf4..0000000000 --- a/framework/base/src/types/managed/wrapped/managed_vec_ref_iter.rs +++ /dev/null @@ -1,103 +0,0 @@ -use crate::api::ManagedTypeApi; - -use super::{ManagedVec, ManagedVecItem}; - -pub struct ManagedVecRefIterator<'a, M, T> -where - M: ManagedTypeApi, - T: ManagedVecItem, -{ - managed_vec: &'a ManagedVec, - byte_start: usize, - byte_end: usize, -} - -impl<'a, M, T> ManagedVecRefIterator<'a, M, T> -where - M: ManagedTypeApi, - T: ManagedVecItem, -{ - pub(crate) fn new(managed_vec: &'a ManagedVec) -> Self { - ManagedVecRefIterator { - managed_vec, - byte_start: 0, - byte_end: managed_vec.byte_len(), - } - } -} - -impl<'a, M, T> Iterator for ManagedVecRefIterator<'a, M, T> -where - M: ManagedTypeApi, - T: ManagedVecItem, -{ - type Item = T::Ref<'a>; - - fn next(&mut self) -> Option { - let next_byte_start = self.byte_start + T::payload_size(); - if next_byte_start > self.byte_end { - return None; - } - let result = unsafe { - T::from_byte_reader_as_borrow(|dest_slice| { - let _ = self - .managed_vec - .buffer - .load_slice(self.byte_start, dest_slice); - }) - }; - - self.byte_start = next_byte_start; - Some(result) - } - - fn size_hint(&self) -> (usize, Option) { - let remaining = (self.byte_end - self.byte_start) / T::payload_size(); - (remaining, Some(remaining)) - } -} - -impl<'a, M, T> ExactSizeIterator for ManagedVecRefIterator<'a, M, T> -where - M: ManagedTypeApi, - T: ManagedVecItem, -{ -} - -impl<'a, M, T> DoubleEndedIterator for ManagedVecRefIterator<'a, M, T> -where - M: ManagedTypeApi, - T: ManagedVecItem, -{ - fn next_back(&mut self) -> Option { - if self.byte_start + T::payload_size() > self.byte_end { - return None; - } - self.byte_end -= T::payload_size(); - - let result = unsafe { - T::from_byte_reader_as_borrow(|dest_slice| { - let _ = self - .managed_vec - .buffer - .load_slice(self.byte_end, dest_slice); - }) - }; - - Some(result) - } -} - -impl<'a, M, T> Clone for ManagedVecRefIterator<'a, M, T> -where - M: ManagedTypeApi, - T: ManagedVecItem, -{ - fn clone(&self) -> Self { - Self { - managed_vec: self.managed_vec, - byte_start: self.byte_start, - byte_end: self.byte_end, - } - } -} 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 new file mode 100644 index 0000000000..37a642648f --- /dev/null +++ b/framework/base/src/types/managed/wrapped/managed_vec_ref_mut.rs @@ -0,0 +1,86 @@ +use crate::{ + api::ManagedTypeApi, + types::{ManagedVec, ManagedVecItem}, +}; +use core::{ + marker::PhantomData, + mem::ManuallyDrop, + ops::{Deref, DerefMut}, +}; + +use super::{ManagedRef, ManagedRefMut}; + +pub struct ManagedVecRefMut<'a, M, T> +where + M: ManagedTypeApi, + T: ManagedVecItem, +{ + _phantom_m: PhantomData, + _phantom_t: PhantomData<&'a mut T>, // needed for the lifetime, even though T is present + managed_vec_handle: M::ManagedBufferHandle, + item_index: usize, + item: ManuallyDrop, +} + +impl ManagedVecRefMut<'_, M, T> +where + M: ManagedTypeApi, + T: ManagedVecItem, +{ + #[inline] + unsafe fn wrap_as_managed_vec( + managed_vec_handle: M::ManagedBufferHandle, + ) -> ManagedRef<'static, M, ManagedVec> { + ManagedRef::wrap_handle(managed_vec_handle) + } + + pub(super) fn new(managed_vec_handle: M::ManagedBufferHandle, item_index: usize) -> Self { + let item = + unsafe { Self::wrap_as_managed_vec(managed_vec_handle.clone()).get_unsafe(item_index) }; + Self { + _phantom_m: PhantomData, + _phantom_t: PhantomData, + managed_vec_handle, + item_index, + item: ManuallyDrop::new(item), + } + } +} + +impl Drop for ManagedVecRefMut<'_, M, T> +where + M: ManagedTypeApi, + T: ManagedVecItem, +{ + fn drop(&mut self) { + let item = unsafe { ManuallyDrop::take(&mut self.item) }; + unsafe { + let _ = + ManagedRefMut::>::wrap_handle(self.managed_vec_handle.clone()) + .set(self.item_index, item); + } + // core::mem::forget(item); + } +} + +impl Deref for ManagedVecRefMut<'_, M, T> +where + M: ManagedTypeApi, + T: ManagedVecItem, +{ + type Target = T; + + fn deref(&self) -> &Self::Target { + &self.item + } +} + +impl DerefMut for ManagedVecRefMut<'_, M, T> +where + M: ManagedTypeApi, + T: ManagedVecItem, +{ + fn deref_mut(&mut self) -> &mut Self::Target { + &mut self.item + } +} diff --git a/framework/base/src/types/managed/wrapped/token_identifier.rs b/framework/base/src/types/managed/wrapped/token_identifier.rs index 1e66615199..39fd17f5e1 100644 --- a/framework/base/src/types/managed/wrapped/token_identifier.rs +++ b/framework/base/src/types/managed/wrapped/token_identifier.rs @@ -9,7 +9,7 @@ use crate::{ types::{ManagedBuffer, ManagedType}, }; -use super::EgldOrEsdtTokenIdentifier; +use super::{EgldOrEsdtTokenIdentifier, ManagedRef}; /// Specialized type for handling token identifiers. /// It wraps a BoxedBytes with the full ASCII name of the token. @@ -26,7 +26,7 @@ impl ManagedType for TokenIdentifier { type OwnHandle = M::ManagedBufferHandle; #[inline] - fn from_handle(handle: M::ManagedBufferHandle) -> Self { + unsafe fn from_handle(handle: M::ManagedBufferHandle) -> Self { TokenIdentifier { buffer: ManagedBuffer::from_handle(handle), } @@ -36,9 +36,17 @@ impl ManagedType for TokenIdentifier { self.buffer.get_handle() } + unsafe fn forget_into_handle(self) -> Self::OwnHandle { + self.buffer.forget_into_handle() + } + fn transmute_from_handle_ref(handle_ref: &M::ManagedBufferHandle) -> &Self { unsafe { core::mem::transmute(handle_ref) } } + + fn transmute_from_handle_ref_mut(handle_ref: &mut M::ManagedBufferHandle) -> &mut Self { + unsafe { core::mem::transmute(handle_ref) } + } } impl TokenIdentifier { @@ -190,17 +198,17 @@ impl TypeAbi for TokenIdentifier { impl SCDisplay for TokenIdentifier { fn fmt(&self, f: &mut F) { - f.append_managed_buffer(&ManagedBuffer::from_handle( - self.buffer.get_handle().cast_or_signal_error::(), - )); + let cast_handle = self.buffer.get_handle().cast_or_signal_error::(); + let wrap_cast = unsafe { ManagedRef::wrap_handle(cast_handle) }; + f.append_managed_buffer(&wrap_cast); } } impl SCLowerHex for TokenIdentifier { fn fmt(&self, f: &mut F) { - f.append_managed_buffer_lower_hex(&ManagedBuffer::from_handle( - self.buffer.get_handle().cast_or_signal_error::(), - )); + let cast_handle = self.buffer.get_handle().cast_or_signal_error::(); + let wrap_cast = unsafe { ManagedRef::wrap_handle(cast_handle) }; + f.append_managed_buffer_lower_hex(&wrap_cast); } } 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/base/src/types/static_buffer/mod.rs b/framework/base/src/types/static_buffer.rs similarity index 100% rename from framework/base/src/types/static_buffer/mod.rs rename to framework/base/src/types/static_buffer.rs diff --git a/framework/base/src/types/static_buffer/sparse_array.rs b/framework/base/src/types/static_buffer/sparse_array.rs index bb3a083243..911069a73d 100644 --- a/framework/base/src/types/static_buffer/sparse_array.rs +++ b/framework/base/src/types/static_buffer/sparse_array.rs @@ -156,7 +156,7 @@ where } } -impl<'a, E, const CAPACITY: usize> Iterator for SparseArrayIterator<'a, E, CAPACITY> +impl Iterator for SparseArrayIterator<'_, E, CAPACITY> where E: ErrorApi, { @@ -179,12 +179,12 @@ where } } -impl<'a, E, const CAPACITY: usize> ExactSizeIterator for SparseArrayIterator<'a, E, CAPACITY> where +impl ExactSizeIterator for SparseArrayIterator<'_, E, CAPACITY> where E: ErrorApi { } -impl<'a, E, const CAPACITY: usize> DoubleEndedIterator for SparseArrayIterator<'a, E, CAPACITY> +impl DoubleEndedIterator for SparseArrayIterator<'_, E, CAPACITY> where E: ErrorApi, { @@ -200,7 +200,7 @@ where } } -impl<'a, E, const CAPACITY: usize> Clone for SparseArrayIterator<'a, E, CAPACITY> +impl Clone for SparseArrayIterator<'_, E, CAPACITY> where E: ErrorApi, { diff --git a/framework/derive/src/contract_impl.rs b/framework/derive/src/contract_impl.rs index 1f6b3c9383..32ee2d76e0 100644 --- a/framework/derive/src/contract_impl.rs +++ b/framework/derive/src/contract_impl.rs @@ -52,7 +52,7 @@ pub fn contract_implementation( impl #trait_name_ident for C where - C: AutoImpl #(#supertraits_main)* + C: AutoImpl #(#supertraits_main)* { #(#auto_impls)* @@ -75,15 +75,17 @@ 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) -> multiversx_sc::types::CallbackSelectorResult { + fn callback_selector(&mut self, ___cb_closure___: &multiversx_sc::types::CallbackClosureForDeser) + -> multiversx_sc::types::CallbackSelectorResult + { #callback_selector_body } - fn callback(&self) { + fn callback(&mut self) { #callback_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::() { - 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( &::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 .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/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::::new(), + &mut multiversx_sc::contract_base::UniversalContractObj::::new(), ); } } @@ -93,7 +93,7 @@ fn generate_wasm_endpoint( A: multiversx_sc::api::VMApi, { super::EndpointWrappers::#call_method_ident( - &multiversx_sc::contract_base::UniversalContractObj::::new(), + &mut multiversx_sc::contract_base::UniversalContractObj::::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 ::external_view_init_override() => { multiversx_sc::external_view_contract::external_view_contract_constructor::(); - 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/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::( - ___cb_closure___.into_arg_loader(), + ___cb_closure___.arg_iter(), #closure_var_names_str, ); } diff --git a/framework/derive/src/generate/snippets.rs b/framework/derive/src/generate/snippets.rs index 6e66eb9ae4..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 - where - A: multiversx_sc::api::VMApi, - { - _phantom: core::marker::PhantomData, - } + pub struct ContractObj(multiversx_sc::contract_base::UniversalContractObj) + 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::(multiversx_sc::contract_base::UniversalContractObj::::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( &self, - ) -> multiversx_sc::types::heap::Box { - multiversx_sc::types::heap::Box::new(ContractObj:: { - _phantom: core::marker::PhantomData, - }) + ) -> multiversx_sc::types::heap::Box + { + multiversx_sc::types::heap::Box::new(self::contract_obj::()) } } } @@ -67,7 +61,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::::new(); + EndpointWrappers::call(&mut obj, fn_name) } } } diff --git a/framework/derive/src/managed_vec_item_derive.rs b/framework/derive/src/managed_vec_item_derive.rs index c65a4c9ee3..f9d7d52671 100644 --- a/framework/derive/src/managed_vec_item_derive.rs +++ b/framework/derive/src/managed_vec_item_derive.rs @@ -43,20 +43,15 @@ fn generate_skips_reserialization_snippets(fields: &syn::Fields) -> Vec Vec { +fn generate_read_from_payload_snippets(fields: &syn::Fields) -> Vec { match fields { syn::Fields::Named(fields_named) => fields_named .named .iter() .map(|field| { let field_ident = &field.ident; - let type_name = &field.ty; quote! { - #field_ident: multiversx_sc::types::ManagedVecItem::from_byte_reader(|bytes| { - let next_index = index + <#type_name as multiversx_sc::types::ManagedVecItem>::payload_size(); - bytes.copy_from_slice(&payload_slice[index .. next_index]); - index = next_index; - }), + #field_ident: multiversx_sc::types::managed_vec_item_read_from_payload_index(payload, &mut index), } }) .collect(), @@ -66,20 +61,15 @@ fn generate_from_byte_reader_snippets(fields: &syn::Fields) -> Vec Vec { +fn generate_save_to_payload_snippets(fields: &syn::Fields) -> Vec { match fields { syn::Fields::Named(fields_named) => fields_named .named .iter() .map(|field| { let field_ident = &field.ident; - let type_name = &field.ty; quote! { - multiversx_sc::types::ManagedVecItem::into_byte_writer(self.#field_ident, |bytes| { - let next_index = index + <#type_name as multiversx_sc::types::ManagedVecItem>::payload_size(); - payload_slice[index .. next_index].copy_from_slice(bytes); - index = next_index; - }); + multiversx_sc::types::managed_vec_item_save_to_payload_index(self.#field_ident, payload, &mut index); } }) .collect(), @@ -89,13 +79,6 @@ fn generate_to_byte_writer_snippets(fields: &syn::Fields) -> Vec proc_macro2::TokenStream { - quote! { - let mut payload = ::new_buffer(); - let payload_slice = multiversx_sc::types::ManagedVecItemPayload::payload_slice_mut(&mut payload); - } -} - fn enum_derive(data_enum: &syn::DataEnum, ast: &syn::DeriveInput) -> TokenStream { let name = &ast.ident; let (impl_generics, ty_generics, where_clause) = &ast.generics.split_for_impl(); @@ -125,24 +108,22 @@ fn enum_derive(data_enum: &syn::DataEnum, ast: &syn::DeriveInput) -> TokenStream const SKIPS_RESERIALIZATION: bool = true; type Ref<'a> = Self; - fn from_byte_reader(mut reader: Reader) -> Self { - let mut arr: [u8; 1] = [0u8; 1]; - reader(&mut arr[..]); - match arr[0] { + fn read_from_payload(payload: &Self::PAYLOAD) -> Self { + let discriminant = ::read_from_payload(payload); + match discriminant { #(#reader_match_arms)* } } - unsafe fn from_byte_reader_as_borrow<'a, Reader: FnMut(&mut [u8])>(reader: Reader) -> Self::Ref<'a> { - Self::from_byte_reader(reader) + unsafe fn borrow_from_payload<'a>(payload: &Self::PAYLOAD) -> Self::Ref<'a> { + Self::read_from_payload(payload) } - fn into_byte_writer R>(self, mut writer: Writer) -> R { - let mut arr: [u8; 1] = [0u8; 1]; - arr[0] = match self { + fn save_to_payload(self, payload: &mut Self::PAYLOAD) { + let discriminant = match self { #(#writer_match_arms)* }; - writer(&arr[..]) + ::save_to_payload(discriminant, payload); } } }; @@ -155,38 +136,34 @@ fn struct_derive(data_struct: &syn::DataStruct, ast: &syn::DeriveInput) -> Token let payload_nested_tuple = generate_payload_nested_tuple(&data_struct.fields); let skips_reserialization_snippets = generate_skips_reserialization_snippets(&data_struct.fields); - let from_byte_reader_snippets = generate_from_byte_reader_snippets(&data_struct.fields); - let to_byte_writer_snippets = generate_to_byte_writer_snippets(&data_struct.fields); - - let payload_buffer_snippet = generate_payload_buffer_snippet(); + let read_from_payload_snippets = generate_read_from_payload_snippets(&data_struct.fields); + let save_to_payload_snippets = generate_save_to_payload_snippets(&data_struct.fields); let gen = quote! { 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 from_byte_reader(mut reader: Reader) -> Self { - #payload_buffer_snippet - reader(payload_slice); + fn read_from_payload(payload: &Self::PAYLOAD) -> Self { let mut index = 0; - #name { - #(#from_byte_reader_snippets)* + unsafe { + #name { + #(#read_from_payload_snippets)* + } } } - unsafe fn from_byte_reader_as_borrow<'a, Reader: FnMut(&mut [u8])>(reader: Reader) -> Self::Ref<'a> { - Self::from_byte_reader(reader) + unsafe fn borrow_from_payload<'a>(payload: &Self::PAYLOAD) -> Self::Ref<'a> { + multiversx_sc::types::ManagedVecRef::new(Self::read_from_payload(payload)) } - fn into_byte_writer R>(self, mut writer: Writer) -> R { - #payload_buffer_snippet + fn save_to_payload(self, payload: &mut Self::PAYLOAD) { let mut index = 0; - - #(#to_byte_writer_snippets)* - - writer(payload_slice) + unsafe { + #(#save_to_payload_snippets)* + } } } }; diff --git a/framework/derive/src/parse/attributes/payable_attr.rs b/framework/derive/src/parse/attributes/payable_attr.rs index 73293719d0..6c0241848f 100644 --- a/framework/derive/src/parse/attributes/payable_attr.rs +++ b/framework/derive/src/parse/attributes/payable_attr.rs @@ -3,7 +3,7 @@ use crate::parse::attributes::util::{clean_string, is_first_char_numeric}; use super::attr_names::*; pub struct PayableAttribute { - pub identifier: Option, + pub identifier: String, } impl PayableAttribute { @@ -24,10 +24,11 @@ impl PayableAttribute { /// Current implementation only works with 1 token name. /// Might be extended in the future. -fn extract_token_identifier(attr: &syn::Attribute) -> Option { +fn extract_token_identifier(attr: &syn::Attribute) -> String { match attr.meta.clone() { syn::Meta::Path(_) => { - panic!("attribute needs 1 string argument: Replace with #[payable(\"*\")] or #[payable(\"EGLD\")]") + // #[payable] + "*".to_owned() }, syn::Meta::List(list) => { let mut iter = list.tokens.into_iter(); @@ -60,7 +61,7 @@ fn extract_token_identifier(attr: &syn::Attribute) -> Option { iter.next().is_none(), "too many tokens in attribute argument" ); - Some(ticker) + ticker }, syn::Meta::NameValue(_) => panic!( "attribute can not be name value. attribute needs 1 string argument: \"*\" or \"EGLD\"" diff --git a/framework/derive/src/parse/method_parse.rs b/framework/derive/src/parse/method_parse.rs index e299912cdd..b5fa90b54d 100644 --- a/framework/derive/src/parse/method_parse.rs +++ b/framework/derive/src/parse/method_parse.rs @@ -16,7 +16,7 @@ use super::{ process_title_attribute, process_upgrade_attribute, process_view_attribute, }; pub struct MethodAttributesPass1 { - pub method_name: String, + pub _method_name: String, pub payable: MethodPayableMetadata, pub only_owner: bool, pub only_admin: bool, @@ -34,7 +34,7 @@ pub fn process_method(m: &syn::TraitItemFn, trait_attributes: &TraitProperties) }; let mut first_pass_data = MethodAttributesPass1 { - method_name: m.sig.ident.to_string(), + _method_name: m.sig.ident.to_string(), payable: MethodPayableMetadata::NotPayable, only_owner: trait_attributes.only_owner, only_admin: trait_attributes.only_admin, diff --git a/framework/derive/src/parse/payable_parse.rs b/framework/derive/src/parse/payable_parse.rs index 91deba4509..99e6c8e17b 100644 --- a/framework/derive/src/parse/payable_parse.rs +++ b/framework/derive/src/parse/payable_parse.rs @@ -5,15 +5,11 @@ pub fn process_payable_attribute( attr: &syn::Attribute, pass_1_data: &mut MethodAttributesPass1, ) -> bool { - PayableAttribute::parse(attr).map(|payable_attr| { - if let Some(identifier) = payable_attr.identifier { - pass_1_data.payable = parse_payable_identifier(identifier.as_str()); - } else { - panic!( - "Endpoint `payable` attribute requires one argument. Replace with `#[payable(\"*\")]` or `#[payable(\"EGLD\")]`. Method name: {}", - &pass_1_data.method_name); - } - }).is_some() + PayableAttribute::parse(attr) + .map(|payable_attr| { + pass_1_data.payable = parse_payable_identifier(&payable_attr.identifier); + }) + .is_some() } fn parse_payable_identifier(identifier: &str) -> MethodPayableMetadata { diff --git a/framework/meta-lib/src/ei/ei_version.rs b/framework/meta-lib/src/ei/ei_version.rs index 6ba2444a6e..33fe86e254 100644 --- a/framework/meta-lib/src/ei/ei_version.rs +++ b/framework/meta-lib/src/ei/ei_version.rs @@ -29,7 +29,7 @@ pub enum EIVersion { #[default] V1_3, - /// Version to be released to mainnet in August 2024. + /// Hooks made available in the Spica release, November 12, 2024: https://multiversx.com/release/release-spica-v1-8-4-0 V1_4, /// Version planned for Q3 2024. 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) diff --git a/framework/meta/src/cmd/code_report/render_code_report.rs b/framework/meta/src/cmd/code_report/render_code_report.rs index e6edcfae8e..f72a05abdf 100644 --- a/framework/meta/src/cmd/code_report/render_code_report.rs +++ b/framework/meta/src/cmd/code_report/render_code_report.rs @@ -61,14 +61,14 @@ impl<'a> CodeReportRender<'a> { fn write_report_for_contract( &mut self, - path: &String, - size: &String, - has_allocator: &String, - has_panic: &String, + path: &str, + size: &str, + has_allocator: &str, + has_panic: &str, ) { self.writeln(format!( "| {} | {} | {} | {} |", - path.split('/').last().unwrap_or_else(|| path), + path.split('/').last().unwrap_or(path), size, has_allocator, has_panic diff --git a/framework/meta/src/cmd/template/template_source.rs b/framework/meta/src/cmd/template/template_source.rs index ea4140cd31..c8f83ac87e 100644 --- a/framework/meta/src/cmd/template/template_source.rs +++ b/framework/meta/src/cmd/template/template_source.rs @@ -16,7 +16,7 @@ pub struct TemplateSource<'a> { pub metadata: TemplateMetadata, } -impl<'a> TemplateSource<'a> { +impl TemplateSource<'_> { pub fn copy_template(&self, target_path: impl AsRef, args_tag: FrameworkVersion) { whitelisted_deep_copy( &self.source_path, diff --git a/framework/scenario/Cargo.toml b/framework/scenario/Cargo.toml index 14c11217af..f5cd1b5ae1 100644 --- a/framework/scenario/Cargo.toml +++ b/framework/scenario/Cargo.toml @@ -50,7 +50,7 @@ version = "0.23.0" path = "../../sdk/scenario-format" [dependencies.multiversx-chain-vm-executor] -version = "0.2.0" +version = "0.3.0" [dependencies.multiversx-chain-vm] version = "=0.11.1" 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 99dc7c6e87..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,26 +75,4 @@ impl From for DebugHandle { } } -impl ManagedVecItem for DebugHandle { - type PAYLOAD = ::PAYLOAD; - - const SKIPS_RESERIALIZATION: bool = ::SKIPS_RESERIALIZATION; - - type Ref<'a> = Self; - - fn from_byte_reader(reader: Reader) -> Self { - use_raw_handle(RawHandle::from_byte_reader(reader)) - } - - unsafe fn from_byte_reader_as_borrow<'a, Reader: FnMut(&mut [u8])>( - reader: Reader, - ) -> Self::Ref<'a> { - use_raw_handle(RawHandle::from_byte_reader(reader)) - } - - fn into_byte_writer R>(self, writer: Writer) -> R { - RawHandle::into_byte_writer(self.get_raw_handle(), writer) - } -} - impl TryStaticCast for DebugHandle {} diff --git a/framework/scenario/src/api/local_api_vh/static_var_api_vh.rs b/framework/scenario/src/api/local_api_vh/static_var_api_vh.rs index e72ae45f74..903094279e 100644 --- a/framework/scenario/src/api/local_api_vh/static_var_api_vh.rs +++ b/framework/scenario/src/api/local_api_vh/static_var_api_vh.rs @@ -1,6 +1,6 @@ use crate::api::{VMHooksApi, VMHooksApiBackend}; use multiversx_sc::{ - api::{use_raw_handle, RawHandle, StaticVarApi, StaticVarApiImpl}, + api::{RawHandle, StaticVarApi, StaticVarApiFlags, StaticVarApiImpl}, types::LockableStaticBuffer, }; @@ -55,30 +55,14 @@ impl StaticVarApiImpl for VMHooksApi { self.with_static_data(|data| data.static_vars_cell.borrow().num_arguments) } - fn set_call_value_egld_handle(&self, handle: RawHandle) { + fn set_flags(&self, flags: StaticVarApiFlags) { self.with_static_data(|data| { - data.static_vars_cell.borrow_mut().call_value_egld_handle = handle; + data.static_vars_cell.borrow_mut().flags = flags; }) } - fn get_call_value_egld_handle(&self) -> RawHandle { - self.with_static_data(|data| { - use_raw_handle(data.static_vars_cell.borrow().call_value_egld_handle) - }) - } - - fn set_call_value_multi_esdt_handle(&self, handle: RawHandle) { - self.with_static_data(|data| { - data.static_vars_cell - .borrow_mut() - .call_value_multi_esdt_handle = handle; - }) - } - - fn get_call_value_multi_esdt_handle(&self) -> RawHandle { - self.with_static_data(|data| { - use_raw_handle(data.static_vars_cell.borrow().call_value_multi_esdt_handle) - }) + fn get_flags(&self) -> StaticVarApiFlags { + self.with_static_data(|data| data.static_vars_cell.borrow().flags) } fn is_scaling_factor_cached(&self, decimals: usize) -> bool { diff --git a/framework/scenario/src/debug_executor/tx_static_vars.rs b/framework/scenario/src/debug_executor/tx_static_vars.rs index 88277694c4..3468d14da6 100644 --- a/framework/scenario/src/debug_executor/tx_static_vars.rs +++ b/framework/scenario/src/debug_executor/tx_static_vars.rs @@ -1,13 +1,13 @@ -use multiversx_sc::api::{const_handles, RawHandle}; +use multiversx_sc::api::{const_handles, RawHandle, StaticVarApiFlags}; #[derive(Debug)] pub struct TxStaticVars { pub external_view_target_address_handle: RawHandle, pub next_handle: RawHandle, pub num_arguments: i32, - pub call_value_egld_handle: RawHandle, - pub call_value_multi_esdt_handle: RawHandle, - //vec of true/false, true if bit from handle = scaling_start + index is not empty + pub flags: StaticVarApiFlags, + + /// Vec of true/false, true if bit from handle = scaling_start + index is not empty pub scaling_factor_init: [bool; const_handles::SCALING_FACTOR_LENGTH], } @@ -17,9 +17,8 @@ impl Default for TxStaticVars { external_view_target_address_handle: 0, next_handle: const_handles::NEW_HANDLE_START_FROM, num_arguments: -1, - call_value_egld_handle: const_handles::UNINITIALIZED_HANDLE, - call_value_multi_esdt_handle: const_handles::UNINITIALIZED_HANDLE, scaling_factor_init: [false; const_handles::SCALING_FACTOR_LENGTH], + flags: StaticVarApiFlags::NONE, } } } diff --git a/framework/scenario/src/facade/expr/file_path.rs b/framework/scenario/src/facade/expr/file_path.rs index 8d779a6fd1..593610ecd6 100644 --- a/framework/scenario/src/facade/expr/file_path.rs +++ b/framework/scenario/src/facade/expr/file_path.rs @@ -12,7 +12,7 @@ const FILE_PREFIX: &str = "file:"; #[derive(Clone, Copy, Debug, PartialEq, Eq)] pub struct FilePath<'a>(pub &'a str); -impl<'a> FilePath<'a> { +impl FilePath<'_> { pub fn eval_to_expr(&self) -> String { format!("{FILE_PREFIX}{}", self.0) } @@ -22,7 +22,7 @@ impl<'a> FilePath<'a> { } } -impl<'a, Env> AnnotatedValue> for FilePath<'a> +impl AnnotatedValue> for FilePath<'_> where Env: ScenarioTxEnv, { @@ -36,9 +36,9 @@ where } } -impl<'a, Env> TxCodeValue for FilePath<'a> where Env: ScenarioTxEnv {} +impl TxCodeValue for FilePath<'_> where Env: ScenarioTxEnv {} -impl<'a> RegisterCodeSource for FilePath<'a> { +impl RegisterCodeSource for FilePath<'_> { fn into_code(self, env_data: ScenarioTxEnvData) -> Vec { self.resolve_contents(&env_data.interpreter_context()) } diff --git a/framework/scenario/src/facade/expr/mxsc_path.rs b/framework/scenario/src/facade/expr/mxsc_path.rs index 465eb5f097..fac10d6a46 100644 --- a/framework/scenario/src/facade/expr/mxsc_path.rs +++ b/framework/scenario/src/facade/expr/mxsc_path.rs @@ -20,7 +20,7 @@ impl<'a> MxscPath<'a> { } } -impl<'a> MxscPath<'a> { +impl MxscPath<'_> { pub fn eval_to_expr(&self) -> String { format!("{MXSC_PREFIX}{}", self.path) } @@ -30,7 +30,7 @@ impl<'a> MxscPath<'a> { } } -impl<'a, Env> AnnotatedValue> for MxscPath<'a> +impl AnnotatedValue> for MxscPath<'_> where Env: ScenarioTxEnv, { @@ -44,9 +44,9 @@ where } } -impl<'a, Env> TxCodeValue for MxscPath<'a> where Env: ScenarioTxEnv {} +impl TxCodeValue for MxscPath<'_> where Env: ScenarioTxEnv {} -impl<'a> RegisterCodeSource for MxscPath<'a> { +impl RegisterCodeSource for MxscPath<'_> { fn into_code(self, env_data: ScenarioTxEnvData) -> Vec { self.resolve_contents(&env_data.interpreter_context()) } diff --git a/framework/scenario/src/facade/expr/num_expr.rs b/framework/scenario/src/facade/expr/num_expr.rs index 704f52496b..55a849c1d3 100644 --- a/framework/scenario/src/facade/expr/num_expr.rs +++ b/framework/scenario/src/facade/expr/num_expr.rs @@ -19,7 +19,7 @@ where BigUint::from_bytes_be(&bytes) } -impl<'a, Env> AnnotatedValue> for NumExpr<'a> +impl AnnotatedValue> for NumExpr<'_> where Env: ScenarioTxEnv, { @@ -32,7 +32,7 @@ where } } -impl<'a, Env> AnnotatedValue for NumExpr<'a> +impl AnnotatedValue for NumExpr<'_> where Env: ScenarioTxEnv, { @@ -45,5 +45,5 @@ where } } -impl<'a, Env> TxEgldValue for NumExpr<'a> where Env: ScenarioTxEnv {} -impl<'a, Env> TxGasValue for NumExpr<'a> where Env: ScenarioTxEnv {} +impl TxEgldValue for NumExpr<'_> where Env: ScenarioTxEnv {} +impl TxGasValue for NumExpr<'_> where Env: ScenarioTxEnv {} diff --git a/framework/scenario/src/facade/result_handlers/expect_error.rs b/framework/scenario/src/facade/result_handlers/expect_error.rs index a06a227424..55e2bde473 100644 --- a/framework/scenario/src/facade/result_handlers/expect_error.rs +++ b/framework/scenario/src/facade/result_handlers/expect_error.rs @@ -8,14 +8,14 @@ use crate::scenario_model::{BytesValue, CheckValue, TxExpect, TxResponse}; /// Can only be used in tests and interactors, not available in contracts. pub struct ExpectError<'a>(pub u64, pub &'a str); -impl<'a, Env, Original> RHListItem for ExpectError<'a> +impl RHListItem for ExpectError<'_> where Env: TxEnv, { type Returns = (); } -impl<'a, Env, Original> RHListItemExec for ExpectError<'a> +impl RHListItemExec for ExpectError<'_> where Env: TxEnv, { diff --git a/framework/scenario/src/facade/result_handlers/expect_message.rs b/framework/scenario/src/facade/result_handlers/expect_message.rs index af5fa2a429..65f412fadd 100644 --- a/framework/scenario/src/facade/result_handlers/expect_message.rs +++ b/framework/scenario/src/facade/result_handlers/expect_message.rs @@ -8,14 +8,14 @@ use crate::scenario_model::{BytesValue, CheckValue, TxExpect, TxResponse, U64Val /// Can only be used in tests and interactors, not available in contracts. pub struct ExpectMessage<'a>(pub &'a str); -impl<'a, Env, Original> RHListItem for ExpectMessage<'a> +impl RHListItem for ExpectMessage<'_> where Env: TxEnv, { type Returns = (); } -impl<'a, Env, Original> RHListItemExec for ExpectMessage<'a> +impl RHListItemExec for ExpectMessage<'_> where Env: TxEnv, { diff --git a/framework/scenario/src/facade/world_tx/scenario_check_state.rs b/framework/scenario/src/facade/world_tx/scenario_check_state.rs index 3f5423419a..182edee26a 100644 --- a/framework/scenario/src/facade/world_tx/scenario_check_state.rs +++ b/framework/scenario/src/facade/world_tx/scenario_check_state.rs @@ -230,7 +230,7 @@ impl<'w> CheckStateBuilder<'w> { } } -impl<'w> Drop for CheckStateBuilder<'w> { +impl Drop for CheckStateBuilder<'_> { fn drop(&mut self) { self.commit_accounts(); } diff --git a/framework/scenario/src/facade/world_tx/scenario_exec_call.rs b/framework/scenario/src/facade/world_tx/scenario_exec_call.rs index 9c1551111b..a856d16d91 100644 --- a/framework/scenario/src/facade/world_tx/scenario_exec_call.rs +++ b/framework/scenario/src/facade/world_tx/scenario_exec_call.rs @@ -23,7 +23,7 @@ pub struct ScenarioEnvExec<'w> { pub data: ScenarioTxEnvData, } -impl<'w> TxEnv for ScenarioEnvExec<'w> { +impl TxEnv for ScenarioEnvExec<'_> { type Api = StaticApi; type RHExpect = TxExpect; @@ -41,7 +41,7 @@ impl<'w> TxEnv for ScenarioEnvExec<'w> { } } -impl<'w> TxEnvMockDeployAddress for ScenarioEnvExec<'w> { +impl TxEnvMockDeployAddress for ScenarioEnvExec<'_> { fn mock_deploy_new_address(&mut self, from: &From, new_address: NA) where From: TxFromSpecified, @@ -65,7 +65,7 @@ impl<'w> TxEnvMockDeployAddress for ScenarioEnvExec<'w> { } } -impl<'w> ScenarioTxEnv for ScenarioEnvExec<'w> { +impl ScenarioTxEnv for ScenarioEnvExec<'_> { fn env_data(&self) -> &ScenarioTxEnvData { &self.data } @@ -115,7 +115,7 @@ where } } -impl<'w> TxEnvWithTxHash for ScenarioEnvExec<'w> { +impl TxEnvWithTxHash for ScenarioEnvExec<'_> { fn set_tx_hash(&mut self, tx_hash: H256) { self.data.set_tx_hash(tx_hash); } diff --git a/framework/scenario/src/facade/world_tx/scenario_query_call.rs b/framework/scenario/src/facade/world_tx/scenario_query_call.rs index dc416439b4..afae3d80e9 100644 --- a/framework/scenario/src/facade/world_tx/scenario_query_call.rs +++ b/framework/scenario/src/facade/world_tx/scenario_query_call.rs @@ -18,7 +18,7 @@ pub struct ScenarioEnvQuery<'w> { pub data: ScenarioTxEnvData, } -impl<'w> TxEnv for ScenarioEnvQuery<'w> { +impl TxEnv for ScenarioEnvQuery<'_> { type Api = StaticApi; type RHExpect = TxExpect; @@ -36,7 +36,7 @@ impl<'w> TxEnv for ScenarioEnvQuery<'w> { } } -impl<'w> ScenarioTxEnv for ScenarioEnvQuery<'w> { +impl ScenarioTxEnv for ScenarioEnvQuery<'_> { fn env_data(&self) -> &ScenarioTxEnvData { &self.data } diff --git a/framework/scenario/src/facade/world_tx/scenario_set_state.rs b/framework/scenario/src/facade/world_tx/scenario_set_state.rs index 3fd44d70b3..ef256453f7 100644 --- a/framework/scenario/src/facade/world_tx/scenario_set_state.rs +++ b/framework/scenario/src/facade/world_tx/scenario_set_state.rs @@ -239,7 +239,7 @@ impl<'w> SetStateBuilderBase<'w> { } } -impl<'w> SetStateBuilder<'w, ()> {} +impl SetStateBuilder<'_, ()> {} impl<'w, Item> SetStateBuilder<'w, Item> where @@ -313,7 +313,7 @@ where pub fn commit(self) {} } -impl<'w, Current> Drop for SetStateBuilder<'w, Current> +impl Drop for SetStateBuilder<'_, Current> where Current: SetStateBuilderItem, { diff --git a/framework/scenario/src/facade/world_tx/scenario_set_state/scenario_set_account.rs b/framework/scenario/src/facade/world_tx/scenario_set_state/scenario_set_account.rs index f5590894e1..a9821659a5 100644 --- a/framework/scenario/src/facade/world_tx/scenario_set_state/scenario_set_account.rs +++ b/framework/scenario/src/facade/world_tx/scenario_set_state/scenario_set_account.rs @@ -38,7 +38,7 @@ impl SetStateBuilderItem for AccountItem { } } -impl<'w> SetStateBuilder<'w, AccountItem> { +impl SetStateBuilder<'_, AccountItem> { pub fn nonce(mut self, nonce: N) -> Self where N: AnnotatedValue, diff --git a/framework/scenario/src/facade/world_tx/scenario_set_state/scenario_set_block.rs b/framework/scenario/src/facade/world_tx/scenario_set_state/scenario_set_block.rs index 3ef0d06cca..e2244207db 100644 --- a/framework/scenario/src/facade/world_tx/scenario_set_state/scenario_set_block.rs +++ b/framework/scenario/src/facade/world_tx/scenario_set_state/scenario_set_block.rs @@ -49,7 +49,7 @@ impl SetStateBuilderItem for BlockItem { } } -impl<'w> SetStateBuilder<'w, BlockItem> { +impl SetStateBuilder<'_, BlockItem> { pub fn block_epoch(mut self, block_epoch: N) -> Self where N: AnnotatedValue, diff --git a/framework/scenario/src/scenario/tx_to_step/tx_to_step_call.rs b/framework/scenario/src/scenario/tx_to_step/tx_to_step_call.rs index 0661806509..752437a130 100644 --- a/framework/scenario/src/scenario/tx_to_step/tx_to_step_call.rs +++ b/framework/scenario/src/scenario/tx_to_step/tx_to_step_call.rs @@ -71,7 +71,7 @@ where step.tx.esdt_value = full_payment_data .multi_esdt .iter() - .map(TxESDT::from) + .map(|item| TxESDT::from(item.clone())) .collect(); } diff --git a/framework/scenario/src/scenario/tx_to_step/tx_to_step_transfer.rs b/framework/scenario/src/scenario/tx_to_step/tx_to_step_transfer.rs index d2baa6bc6c..782f86dc16 100644 --- a/framework/scenario/src/scenario/tx_to_step/tx_to_step_transfer.rs +++ b/framework/scenario/src/scenario/tx_to_step/tx_to_step_transfer.rs @@ -52,7 +52,7 @@ where step.tx.esdt_value = full_payment_data .multi_esdt .iter() - .map(TxESDT::from) + .map(|item| TxESDT::from(item.clone())) .collect(); } diff --git a/framework/scenario/tests/contract_without_macros.rs b/framework/scenario/tests/contract_without_macros.rs index c597bb9e81..d0da5fac52 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::(); let result = self.version(); multiversx_sc::io::finish_multi::(&result) } - fn call_some_async(&self) { + fn call_some_async(&mut self) { self.some_async(); multiversx_sc::io::finish_multi::(&()) } - 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, + ___cb_closure___: &multiversx_sc::types::CallbackClosureForDeser, + ) -> multiversx_sc::types::CallbackSelectorResult { + multiversx_sc::types::CallbackSelectorResult::NotProcessed } } @@ -251,8 +254,6 @@ mod sample_adder { ///////////////////////////////////////////////////////////////////////////////////////////////// pub trait AutoImpl: multiversx_sc::contract_base::ContractBase {} - // impl super::module_1::AutoImpl for C where C: AutoImpl {} - impl Adder for C where C: AutoImpl + super::module_1::AutoImpl, @@ -277,7 +278,7 @@ mod sample_adder { Adder + multiversx_sc::contract_base::ContractBase + super::module_1::EndpointWrappers { #[inline] - fn call_sum(&self) { + fn call_sum(&mut self) { ::init_static(); multiversx_sc::io::call_value_init::not_payable::(); let () = multiversx_sc::io::load_endpoint_args::(()); @@ -285,7 +286,7 @@ mod sample_adder { multiversx_sc::io::finish_multi::(&result); } #[inline] - fn call_init(&self) { + fn call_init(&mut self) { ::init_static(); multiversx_sc::io::call_value_init::not_payable::(); let (initial_value, ()) = multiversx_sc::io::load_endpoint_args::< @@ -295,7 +296,7 @@ mod sample_adder { self.init(initial_value); } #[inline] - fn call_upgrade(&self) { + fn call_upgrade(&mut self) { ::init_static(); multiversx_sc::io::call_value_init::not_payable::(); let (initial_value, ()) = multiversx_sc::io::load_endpoint_args::< @@ -305,7 +306,7 @@ mod sample_adder { self.upgrade(initial_value); } #[inline] - fn call_add(&self) { + fn call_add(&mut self) { ::init_static(); multiversx_sc::io::call_value_init::not_payable::(); let (value, ()) = multiversx_sc::io::load_endpoint_args::< @@ -314,8 +315,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 +347,43 @@ 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 ___cb_closure___: multiversx_sc::types::CallbackClosureForDeser, - ) -> multiversx_sc::types::CallbackSelectorResult { - multiversx_sc::types::CallbackSelectorResult::NotProcessed(___cb_closure___) + &mut self, + ___cb_closure___: &multiversx_sc::types::CallbackClosureForDeser, + ) -> multiversx_sc::types::CallbackSelectorResult { + let ___cb_closure_matcher___ = ___cb_closure___.matcher::<32usize>(); + if ___cb_closure_matcher___.matches_empty() { + return multiversx_sc::types::CallbackSelectorResult::Processed; + } + if super::module_1::EndpointWrappers::callback_selector(self, ___cb_closure___) + .is_processed() + { + return multiversx_sc::types::CallbackSelectorResult::Processed; + } + multiversx_sc::types::CallbackSelectorResult::NotProcessed + } + fn callback(&mut self) { + if let Some(___cb_closure___) = + multiversx_sc::types::CallbackClosureForDeser::storage_load_and_clear::() + { + if !self::EndpointWrappers::callback_selector(self, &___cb_closure___) + .is_processed() + { + multiversx_sc::api::ErrorApiImpl::signal_error( + &::error_api_impl(), + err_msg::CALLBACK_BAD_FUNC.as_bytes(), + ); + } + } } - fn callback(&self) {} } impl EndpointWrappers for multiversx_sc::contract_base::UniversalContractObj where @@ -441,7 +466,7 @@ mod sample_adder { A: multiversx_sc::api::VMApi, { super::EndpointWrappers::call_sum( - &multiversx_sc::contract_base::UniversalContractObj::::new(), + &mut multiversx_sc::contract_base::UniversalContractObj::::new(), ); } pub fn init() @@ -449,7 +474,7 @@ mod sample_adder { A: multiversx_sc::api::VMApi, { super::EndpointWrappers::call_init( - &multiversx_sc::contract_base::UniversalContractObj::::new(), + &mut multiversx_sc::contract_base::UniversalContractObj::::new(), ); } pub fn upgrade() @@ -457,7 +482,7 @@ mod sample_adder { A: multiversx_sc::api::VMApi, { super::EndpointWrappers::call_upgrade( - &multiversx_sc::contract_base::UniversalContractObj::::new(), + &mut multiversx_sc::contract_base::UniversalContractObj::::new(), ); } pub fn add() @@ -465,7 +490,7 @@ mod sample_adder { A: multiversx_sc::api::VMApi, { super::EndpointWrappers::call_add( - &multiversx_sc::contract_base::UniversalContractObj::::new(), + &mut multiversx_sc::contract_base::UniversalContractObj::::new(), ); } pub fn callBack() @@ -473,7 +498,7 @@ mod sample_adder { A: multiversx_sc::api::VMApi, { super::EndpointWrappers::callback( - &multiversx_sc::contract_base::UniversalContractObj::::new(), + &mut multiversx_sc::contract_base::UniversalContractObj::::new(), ); } } @@ -567,12 +592,9 @@ mod sample_adder { ///////////////////////////////////////////////////////////////////////////////////////////////// //////// CONTRACT OBJECT //////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////////////////////// - pub struct ContractObj + pub struct ContractObj(multiversx_sc::contract_base::UniversalContractObj) where - A: multiversx_sc::api::VMApi, - { - _phantom: core::marker::PhantomData, - } + A: multiversx_sc::api::VMApi; ///////////////////////////////////////////////////////////////////////////////////////////////// //////// CONTRACT OBJECT as CONTRACT BASE /////////////////////////////////////////////////////// @@ -597,7 +619,10 @@ mod sample_adder { A: multiversx_sc::api::VMApi, { fn call(&self, fn_name: &str) -> bool { - EndpointWrappers::call(self, fn_name) + // creating a new object, which we can mutate + // because of dynamic traits, we cannot move `self` + let mut obj = multiversx_sc::contract_base::UniversalContractObj::::new(); + EndpointWrappers::call(&mut obj, fn_name) } } @@ -605,19 +630,17 @@ mod sample_adder { where A: multiversx_sc::api::VMApi, { - ContractObj { - _phantom: core::marker::PhantomData, - } + ContractObj::(multiversx_sc::contract_base::UniversalContractObj::::new()) } + pub struct ContractBuilder; + impl multiversx_sc::contract_base::CallableContractBuilder for self::ContractBuilder { fn new_contract_obj( &self, ) -> multiversx_sc::types::heap::Box { - multiversx_sc::types::heap::Box::new(ContractObj:: { - _phantom: core::marker::PhantomData, - }) + multiversx_sc::types::heap::Box::new(self::contract_obj::()) } } @@ -770,8 +793,10 @@ fn contract_without_macros_basic() { assert_eq!(BigInt::from(100), adder.version()); + let adder = sample_adder::ContractBuilder.new_contract_obj::(); assert!(!adder.call("invalid_endpoint")); + let adder = sample_adder::ContractBuilder.new_contract_obj::(); assert!(adder.call("getSum")); let mut own_proxy = 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 6efd920acc..7f0d06be8f 100644 --- a/framework/scenario/tests/derive_managed_vec_item_biguint_test.rs +++ b/framework/scenario/tests/derive_managed_vec_item_biguint_test.rs @@ -1,7 +1,9 @@ use multiversx_sc::{ api::ManagedTypeApi, - codec, - codec::derive::{NestedDecode, NestedEncode, TopDecode, TopEncode}, + codec::{ + self, + derive::{NestedDecode, NestedEncode, TopDecode, TopEncode}, + }, derive::ManagedVecItem, types::{BigUint, ManagedType, ManagedVecItemPayload}, }; @@ -39,20 +41,15 @@ fn managed_struct_to_bytes_writer() { num: 0x12345, }; - let mut payload = as multiversx_sc::types::ManagedVecItem>::PAYLOAD::new_buffer(); - let payload_slice = payload.payload_slice_mut(); - let handle_bytes = s.big_uint.get_handle().to_be_bytes(); let expected = [0xff, 0xff, 0xff, handle_bytes[3], 0x00, 0x01, 0x23, 0x45]; - as multiversx_sc::types::ManagedVecItem>::into_byte_writer( + let mut payload = as multiversx_sc::types::ManagedVecItem>::PAYLOAD::new_buffer(); + as multiversx_sc::types::ManagedVecItem>::save_to_payload( s, - |bytes| { - payload_slice.copy_from_slice(bytes); - - assert_eq!(payload_slice, expected); - }, + &mut payload, ); + assert_eq!(payload.buffer, expected); } #[test] @@ -65,14 +62,8 @@ fn managed_struct_from_bytes_reader() { let arr: [u8; 8] = [0xff, 0xff, 0xff, handle_bytes[3], 0x00, 0x01, 0x23, 0x45]; let struct_from_bytes = - as multiversx_sc::types::ManagedVecItem>::from_byte_reader( - |bytes| { - bytes.copy_from_slice( - &arr - [0 - .. as multiversx_sc::types::ManagedVecItem>::payload_size()], - ); - }, + as multiversx_sc::types::ManagedVecItem>::read_from_payload( + &arr.into() ); assert_eq!(s, struct_from_bytes); } 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 1018747da3..c6dea79b94 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 @@ -1,7 +1,9 @@ use multiversx_sc::{ api::ManagedTypeApi, - codec, - codec::derive::{NestedDecode, NestedEncode, TopDecode, TopEncode}, + codec::{ + self, + derive::{NestedDecode, NestedEncode, TopDecode, TopEncode}, + }, derive::ManagedVecItem, types::{ BigUint, EsdtTokenPayment, ManagedByteArray, ManagedType, ManagedVecItemPayload, @@ -50,9 +52,6 @@ fn struct_to_bytes_writer() { eth_address_2: ManagedByteArray::new_from_bytes(&[2u8; 20]), }; - let mut payload = as multiversx_sc::types::ManagedVecItem>::PAYLOAD::new_buffer(); - let payload_slice = payload.payload_slice_mut(); - let handle1 = s.token.token_identifier.get_handle().to_be_bytes(); let handle2 = s.token.amount.get_handle().to_be_bytes(); let handle3 = s.eth_address_1.get_handle().to_be_bytes(); @@ -63,14 +62,12 @@ fn struct_to_bytes_writer() { handle3[1], handle3[2], handle3[3], handle4[0], handle4[1], handle4[2], handle4[3], ]; - as multiversx_sc::types::ManagedVecItem>::into_byte_writer( + let mut payload = as multiversx_sc::types::ManagedVecItem>::PAYLOAD::new_buffer(); + as multiversx_sc::types::ManagedVecItem>::save_to_payload( s, - |bytes| { - payload_slice.copy_from_slice(bytes); - - assert_eq!(payload_slice, expected); - }, + &mut payload, ); + assert_eq!(payload.buffer, expected); } #[test] @@ -93,14 +90,8 @@ fn struct_from_bytes_reader() { ]; let struct_from_bytes = - as multiversx_sc::types::ManagedVecItem>::from_byte_reader( - |bytes| { - bytes.copy_from_slice( - &arr - [0 - .. as multiversx_sc::types::ManagedVecItem>::payload_size()], - ); - }, + as multiversx_sc::types::ManagedVecItem>::read_from_payload( + &arr.into() ); assert_eq!(s, struct_from_bytes); diff --git a/framework/scenario/tests/derive_managed_vec_item_simple_enum.rs b/framework/scenario/tests/derive_managed_vec_item_simple_enum.rs index 46dcceed33..5a41283613 100644 --- a/framework/scenario/tests/derive_managed_vec_item_simple_enum.rs +++ b/framework/scenario/tests/derive_managed_vec_item_simple_enum.rs @@ -1,7 +1,10 @@ use multiversx_sc::{ - codec, - codec::derive::{NestedDecode, NestedEncode, TopDecode, TopEncode}, + codec::{ + self, + derive::{NestedDecode, NestedEncode, TopDecode, TopEncode}, + }, derive::ManagedVecItem, + types::{ManagedVecItemPayload, ManagedVecItemPayloadBuffer}, }; // to test, run the following command in the crate folder: @@ -27,21 +30,18 @@ fn enum_static() { #[test] fn enum_to_bytes_writer() { - ::into_byte_writer( + let mut payload = ManagedVecItemPayloadBuffer::new_buffer(); + ::save_to_payload( SimpleEnum::Variant1, - |bytes| { - assert_eq!(bytes.len(), 1); - assert_eq!(bytes[0], 0); - }, + &mut payload, ); + + assert_eq!(payload.buffer, [0]); } #[test] fn enum_from_bytes_reader() { let enum_from_bytes = - ::from_byte_reader(|bytes| { - assert_eq!(bytes.len(), 1); - bytes[0] = 1; - }); + ::read_from_payload(&[1u8].into()); assert_eq!(enum_from_bytes, SimpleEnum::Variant2); } 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 e55e6d9140..20746bcb80 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 @@ -65,18 +65,14 @@ fn struct_1_to_bytes_writer() { }; let mut payload = ::PAYLOAD::new_buffer(); - let payload_slice = payload.payload_slice_mut(); - - ::into_byte_writer(s, |bytes| { - payload_slice.copy_from_slice(bytes); - assert_eq!( - payload_slice, - [ - 0x01, 0x00, 0x02, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x04, 0x01, - ] - ); - }); + ::save_to_payload(s, &mut payload); + assert_eq!( + payload.buffer, + [ + 0x01, 0x00, 0x02, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x04, 0x01, + ] + ); } #[test] @@ -94,10 +90,6 @@ fn struct_1_from_bytes_reader() { ]; let struct_from_bytes = - ::from_byte_reader(|bytes| { - bytes.copy_from_slice( - &arr[0..::payload_size()], - ); - }); + ::read_from_payload(&arr.into()); 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 50bea73aac..641bb04a0b 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 @@ -1,3 +1,5 @@ +use multiversx_sc::types::{ManagedVecItemPayload, ManagedVecItemPayloadBuffer}; + multiversx_sc::derive_imports!(); // to test, run the following command in the crate folder: @@ -49,9 +51,9 @@ fn struct_to_bytes_writer() { /* arr */ 0x61, 0x11, 0x62, 0x22, ]; - ::into_byte_writer(s, |bytes| { - assert_eq!(bytes, &expected_payload[..]); - }); + let mut payload = ManagedVecItemPayloadBuffer::new_buffer(); + ::save_to_payload(s, &mut payload); + assert_eq!(payload.buffer, &expected_payload[..]); } #[test] @@ -67,7 +69,7 @@ fn struct_2_from_bytes_reader() { }; #[rustfmt::skip] - let payload = &[ + let payload = [ /* u_8 */ 0x01, /* u_16 */ 0x00, 0x02, /* u_32 */ 0x00, 0x00, 0x00, 0x03, @@ -78,8 +80,6 @@ fn struct_2_from_bytes_reader() { ]; let struct_from_bytes = - ::from_byte_reader(|bytes| { - bytes.copy_from_slice(&payload[..]); - }); + ::read_from_payload(&payload.into()); 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 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()); } diff --git a/framework/snippets/Cargo.toml b/framework/snippets/Cargo.toml index 3c8f4b9e09..a78ffc1938 100644 --- a/framework/snippets/Cargo.toml +++ b/framework/snippets/Cargo.toml @@ -27,8 +27,9 @@ log = "0.4.17" env_logger = "0.11" futures = "0.3" anyhow = "1.0.44" +serde_json = "1.0" -tokio = { version = "1.24", features = ["full"], optional = true} +tokio = { version = "1.24", features = ["full"], optional = true } [dependencies.multiversx-sc-scenario] version = "=0.54.6" @@ -52,6 +53,3 @@ default-features = false version = "=0.7.1" path = "../../sdk/dapp" optional = true - -[dev-dependencies] -serde_json = "1.0" diff --git a/framework/snippets/src/account_tool.rs b/framework/snippets/src/account_tool.rs index b0a5ccc220..eefc51642f 100644 --- a/framework/snippets/src/account_tool.rs +++ b/framework/snippets/src/account_tool.rs @@ -4,7 +4,7 @@ use multiversx_sc_scenario::{ imports::Bech32Address, scenario_model::{Account, BytesKey, BytesValue, Scenario, SetStateStep, Step}, }; -use multiversx_sdk::gateway::GatewayAsyncService; +use multiversx_sdk::gateway::{GatewayAsyncService, SetStateAccount}; use multiversx_sdk::gateway::{ GetAccountEsdtRolesRequest, GetAccountEsdtTokensRequest, GetAccountRequest, GetAccountStorageRequest, @@ -20,7 +20,7 @@ pub async fn print_account_as_scenario_set_state Scenario { pub async fn retrieve_account_as_scenario_set_state( api: &GatewayProxy, bech32_address: &Bech32Address, -) -> SetStateStep { +) -> (SetStateAccount, SetStateStep) { let address = bech32_address.as_address(); let sdk_account = api.request(GetAccountRequest::new(address)).await.unwrap(); @@ -63,14 +63,18 @@ pub async fn retrieve_account_as_scenario_set_state where @@ -85,9 +88,33 @@ where } pub async fn retrieve_account(&mut self, wallet_address: &Bech32Address) { - let set_state = retrieve_account_as_scenario_set_state(&self.proxy, wallet_address).await; - self.pre_runners.run_set_state_step(&set_state); - self.post_runners.run_set_state_step(&set_state); + let (set_state_account, set_state_step) = + retrieve_account_as_scenario_set_state(&self.proxy, wallet_address).await; + self.pre_runners.run_set_state_step(&set_state_step); + self.post_runners.run_set_state_step(&set_state_step); + + let path = self.get_state_file_path(); + set_state_account.add_to_state_file(path.as_path()); + } + + pub fn get_state_file_path(&self) -> PathBuf { + self.current_dir.join(INTERACTOR_SET_STATE_PATH) + } + + pub fn get_accounts_from_file(&self) -> Vec { + let file_path = self.get_state_file_path(); + + if !file_path.exists() { + return Vec::new(); + } + + let file = File::open(file_path).expect("Failed to open state file"); + let reader = BufReader::new(file); + + serde_json::from_reader(reader).unwrap_or_else(|_| { + println!("Failed to parse state file; returning an empty list of accounts"); + Vec::new() + }) } /// Tells the interactor where the crate lies relative to the workspace. diff --git a/framework/snippets/src/interactor/interactor_chain_simulator.rs b/framework/snippets/src/interactor/interactor_chain_simulator.rs index 44943fe243..88fa701fe0 100644 --- a/framework/snippets/src/interactor/interactor_chain_simulator.rs +++ b/framework/snippets/src/interactor/interactor_chain_simulator.rs @@ -1,7 +1,8 @@ use anyhow::Error; use multiversx_sc_scenario::imports::Address; use multiversx_sdk::gateway::{ - ChainSimulatorGenerateBlocksRequest, ChainSimulatorSendFundsRequest, GatewayAsyncService, + ChainSimulatorGenerateBlocksRequest, ChainSimulatorSendFundsRequest, + ChainSimulatorSetStateRequest, GatewayAsyncService, SetStateAccount, }; use crate::InteractorBase; @@ -53,4 +54,25 @@ where )) .await } + + pub async fn set_state(&self, accounts: Vec) -> Result { + if !self.use_chain_simulator { + return Ok(String::from("no-simulator")); + } + + self.proxy + .request(ChainSimulatorSetStateRequest::for_accounts(accounts)) + .await + } + + pub async fn set_state_for_saved_accounts(&self) -> Result { + if !self.use_chain_simulator { + return Ok(String::from("no-simulator")); + } + + let accounts = self.get_accounts_from_file(); + self.proxy + .request(ChainSimulatorSetStateRequest::for_accounts(accounts)) + .await + } } diff --git a/framework/snippets/src/interactor/interactor_sender.rs b/framework/snippets/src/interactor/interactor_sender.rs index e3877dec0a..4ba0efa162 100644 --- a/framework/snippets/src/interactor/interactor_sender.rs +++ b/framework/snippets/src/interactor/interactor_sender.rs @@ -1,7 +1,10 @@ +use std::collections::HashMap; + use crate::sdk::{data::transaction::Transaction, wallet::Wallet}; use log::debug; use multiversx_sc_scenario::multiversx_sc::types::Address; -use multiversx_sdk::gateway::{GatewayAsyncService, GetAccountRequest}; +use multiversx_sdk::data::account::Account; +use multiversx_sdk::gateway::{GatewayAsyncService, GetAccountRequest, GetAccountStorageRequest}; use crate::InteractorBase; @@ -25,6 +28,20 @@ where account.nonce } + pub async fn get_account(&self, address: &Address) -> Account { + self.proxy + .request(GetAccountRequest::new(address)) + .await + .expect("failed to retrieve account") + } + + pub async fn get_account_storage(&self, address: &Address) -> HashMap { + self.proxy + .request(GetAccountStorageRequest::new(address)) + .await + .expect("failed to retrieve account") + } + pub(crate) async fn set_nonce_and_sign_tx( &mut self, sender_address: &Address, diff --git a/framework/snippets/src/interactor/interactor_tx/interactor_exec_env.rs b/framework/snippets/src/interactor/interactor_tx/interactor_exec_env.rs index c7987d28e6..ba01813f9c 100644 --- a/framework/snippets/src/interactor/interactor_tx/interactor_exec_env.rs +++ b/framework/snippets/src/interactor/interactor_tx/interactor_exec_env.rs @@ -30,7 +30,7 @@ where pub data: ScenarioTxEnvData, } -impl<'w, GatewayProxy> TxEnv for InteractorEnvExec<'w, GatewayProxy> +impl TxEnv for InteractorEnvExec<'_, GatewayProxy> where GatewayProxy: GatewayAsyncService, { @@ -51,7 +51,7 @@ where } } -impl<'w, GatewayProxy> ScenarioTxEnv for InteractorEnvExec<'w, GatewayProxy> +impl ScenarioTxEnv for InteractorEnvExec<'_, GatewayProxy> where GatewayProxy: GatewayAsyncService, { @@ -60,7 +60,7 @@ where } } -impl<'w, GatewayProxy> TxEnvWithTxHash for InteractorEnvExec<'w, GatewayProxy> +impl TxEnvWithTxHash for InteractorEnvExec<'_, GatewayProxy> where GatewayProxy: GatewayAsyncService, { diff --git a/framework/snippets/src/interactor/interactor_tx/interactor_exec_transf.rs b/framework/snippets/src/interactor/interactor_tx/interactor_exec_transf.rs index bb7559ba93..1dade9dc6b 100644 --- a/framework/snippets/src/interactor/interactor_tx/interactor_exec_transf.rs +++ b/framework/snippets/src/interactor/interactor_tx/interactor_exec_transf.rs @@ -54,7 +54,7 @@ where } } -impl<'w, GatewayProxy> InteractorExecStep<'w, GatewayProxy, TransferStep, ()> +impl InteractorExecStep<'_, GatewayProxy, TransferStep, ()> where GatewayProxy: GatewayAsyncService, { diff --git a/framework/snippets/src/interactor/interactor_tx/interactor_query_env.rs b/framework/snippets/src/interactor/interactor_tx/interactor_query_env.rs index 25d0b5e822..dbd2066a66 100644 --- a/framework/snippets/src/interactor/interactor_tx/interactor_query_env.rs +++ b/framework/snippets/src/interactor/interactor_tx/interactor_query_env.rs @@ -27,7 +27,7 @@ where pub data: ScenarioTxEnvData, } -impl<'w, GatewayProxy> TxEnv for InteractorEnvQuery<'w, GatewayProxy> +impl TxEnv for InteractorEnvQuery<'_, GatewayProxy> where GatewayProxy: GatewayAsyncService, { @@ -48,7 +48,7 @@ where } } -impl<'w, GatewayProxy> ScenarioTxEnv for InteractorEnvQuery<'w, GatewayProxy> +impl ScenarioTxEnv for InteractorEnvQuery<'_, GatewayProxy> where GatewayProxy: GatewayAsyncService, { diff --git a/framework/snippets/src/multi/interactor_step.rs b/framework/snippets/src/multi/interactor_step.rs index 93a93d6a9e..b8df05a9a5 100644 --- a/framework/snippets/src/multi/interactor_step.rs +++ b/framework/snippets/src/multi/interactor_step.rs @@ -13,7 +13,7 @@ pub enum InteractorStepRef<'a> { ScDeploy(&'a mut ScDeployStep), } -impl<'a> InteractorStepRef<'a> { +impl InteractorStepRef<'_> { pub fn to_transaction( &self, interactor: &InteractorBase, diff --git a/framework/wasm-adapter/src/api/managed_types/static_var_api_node.rs b/framework/wasm-adapter/src/api/managed_types/static_var_api_node.rs index 501d53d68f..3c6b19996f 100644 --- a/framework/wasm-adapter/src/api/managed_types/static_var_api_node.rs +++ b/framework/wasm-adapter/src/api/managed_types/static_var_api_node.rs @@ -1,5 +1,5 @@ use multiversx_sc::{ - api::{const_handles, RawHandle, StaticVarApi, StaticVarApiImpl}, + api::{const_handles, RawHandle, StaticVarApi, StaticVarApiFlags, StaticVarApiImpl}, types::LockableStaticBuffer, }; @@ -9,8 +9,7 @@ static mut STATIC_BUFFER: LockableStaticBuffer = LockableStaticBuffer::new(); static mut EXTERNAL_VIEW_TARGET_ADDRESS_HANDLE: i32 = 0; static mut NEXT_HANDLE: i32 = const_handles::NEW_HANDLE_START_FROM; static mut NUM_ARGUMENTS: i32 = 0; -static mut CALL_VALUE_EGLD_HANDLE: i32 = const_handles::UNINITIALIZED_HANDLE; -static mut CALL_VALUE_MULTI_ESDT_HANDLE: i32 = const_handles::UNINITIALIZED_HANDLE; +static mut FLAGS: StaticVarApiFlags = StaticVarApiFlags::NONE; static mut SCALING_FACTOR_INIT: [bool; const_handles::SCALING_FACTOR_LENGTH] = [false; const_handles::SCALING_FACTOR_LENGTH]; @@ -62,24 +61,14 @@ impl StaticVarApiImpl for VmApiImpl { unsafe { NUM_ARGUMENTS } } - fn set_call_value_egld_handle(&self, handle: RawHandle) { + fn set_flags(&self, flags: StaticVarApiFlags) { unsafe { - CALL_VALUE_EGLD_HANDLE = handle; + FLAGS = flags; } } - fn get_call_value_egld_handle(&self) -> RawHandle { - unsafe { CALL_VALUE_EGLD_HANDLE } - } - - fn set_call_value_multi_esdt_handle(&self, handle: RawHandle) { - unsafe { - CALL_VALUE_MULTI_ESDT_HANDLE = handle; - } - } - - fn get_call_value_multi_esdt_handle(&self) -> RawHandle { - unsafe { CALL_VALUE_MULTI_ESDT_HANDLE } + fn get_flags(&self) -> StaticVarApiFlags { + unsafe { FLAGS } } fn is_scaling_factor_cached(&self, decimals: usize) -> bool { diff --git a/framework/wasm-adapter/src/api/unsafe_buffer.rs b/framework/wasm-adapter/src/api/unsafe_buffer.rs index c18034de6b..8794203daa 100644 --- a/framework/wasm-adapter/src/api/unsafe_buffer.rs +++ b/framework/wasm-adapter/src/api/unsafe_buffer.rs @@ -11,10 +11,12 @@ static mut BUFFER_1: [u8; BUFFER_1_SIZE] = [0u8; BUFFER_1_SIZE]; /// The second buffer is for when the first one is busy with something else. static mut BUFFER_2: [u8; BUFFER_2_SIZE] = [0u8; BUFFER_2_SIZE]; +#[allow(static_mut_refs)] pub(crate) unsafe fn buffer_1_ptr() -> *mut u8 { BUFFER_1.as_mut_ptr() } +#[allow(static_mut_refs)] pub(crate) unsafe fn buffer_2_ptr() -> *mut u8 { BUFFER_2.as_mut_ptr() } diff --git a/framework/wasm-adapter/src/wasm_alloc/leaking_allocator.rs b/framework/wasm-adapter/src/wasm_alloc/leaking_allocator.rs index 8a40b0ac68..06e246f0e4 100644 --- a/framework/wasm-adapter/src/wasm_alloc/leaking_allocator.rs +++ b/framework/wasm-adapter/src/wasm_alloc/leaking_allocator.rs @@ -45,7 +45,7 @@ unsafe impl GlobalAlloc for LeakingAllocator { if new_total > *size { // Request enough new space for this allocation, even if we have some space left over from the last one incase they end up non-contiguous. // Round up to a number of pages - let requested_pages = (requested_size + PAGE_SIZE - 1) / PAGE_SIZE; + let requested_pages = requested_size.div_ceil(PAGE_SIZE); let previous_page_count = memory_grow(PageCount(requested_pages)); let previous_size = previous_page_count.size_in_bytes(); diff --git a/sdk/core/src/crypto/public_key.rs b/sdk/core/src/crypto/public_key.rs index 448bf57e9d..6ad8604ecb 100644 --- a/sdk/core/src/crypto/public_key.rs +++ b/sdk/core/src/crypto/public_key.rs @@ -34,7 +34,7 @@ impl PublicKey { } } -impl<'a> From<&'a PrivateKey> for PublicKey { +impl From<&PrivateKey> for PublicKey { fn from(private_key: &PrivateKey) -> PublicKey { let bytes = private_key.to_bytes(); diff --git a/sdk/core/src/gateway.rs b/sdk/core/src/gateway.rs index 1512717a85..f3e08a4af2 100644 --- a/sdk/core/src/gateway.rs +++ b/sdk/core/src/gateway.rs @@ -5,6 +5,7 @@ mod gateway_account_storage; mod gateway_block; mod gateway_chain_simulator_blocks; mod gateway_chain_simulator_send_funds; +mod gateway_chain_simulator_set_state; mod gateway_network_config; mod gateway_network_economics; mod gateway_network_status; @@ -23,6 +24,7 @@ pub use gateway_account_storage::GetAccountStorageRequest; pub use gateway_block::GetHyperBlockRequest; pub use gateway_chain_simulator_blocks::ChainSimulatorGenerateBlocksRequest; pub use gateway_chain_simulator_send_funds::ChainSimulatorSendFundsRequest; +pub use gateway_chain_simulator_set_state::{ChainSimulatorSetStateRequest, SetStateAccount}; pub use gateway_network_config::NetworkConfigRequest; pub use gateway_network_economics::NetworkEconimicsRequest; pub use gateway_network_status::NetworkStatusRequest; @@ -61,6 +63,7 @@ const GENERATE_BLOCKS_UNTIL_TX_PROCESSED_ENDPOINT: &str = "simulator/generate-blocks-until-transaction-processed"; const GENERATE_BLOCKS_UNTIL_EPOCH_REACHED_ENDPOINT: &str = "simulator/generate-blocks-until-epoch-reached"; +const SET_STATE_ENDPOINT: &str = "simulator/set-state"; pub enum GatewayRequestType { Get, diff --git a/sdk/core/src/gateway/gateway_account.rs b/sdk/core/src/gateway/gateway_account.rs index 76eee4c736..913c55d0eb 100644 --- a/sdk/core/src/gateway/gateway_account.rs +++ b/sdk/core/src/gateway/gateway_account.rs @@ -16,7 +16,7 @@ impl<'a> GetAccountRequest<'a> { } } -impl<'a> GatewayRequest for GetAccountRequest<'a> { +impl GatewayRequest for GetAccountRequest<'_> { type Payload = (); type DecodedJson = AccountResponse; type Result = Account; diff --git a/sdk/core/src/gateway/gateway_account_esdt_roles.rs b/sdk/core/src/gateway/gateway_account_esdt_roles.rs index 421edd81b2..d7b19e8e41 100644 --- a/sdk/core/src/gateway/gateway_account_esdt_roles.rs +++ b/sdk/core/src/gateway/gateway_account_esdt_roles.rs @@ -16,7 +16,7 @@ impl<'a> GetAccountEsdtRolesRequest<'a> { } } -impl<'a> GatewayRequest for GetAccountEsdtRolesRequest<'a> { +impl GatewayRequest for GetAccountEsdtRolesRequest<'_> { type Payload = (); type DecodedJson = EsdtRolesResponse; type Result = HashMap>; diff --git a/sdk/core/src/gateway/gateway_account_esdt_tokens.rs b/sdk/core/src/gateway/gateway_account_esdt_tokens.rs index 72e27e54a9..e2916fe840 100644 --- a/sdk/core/src/gateway/gateway_account_esdt_tokens.rs +++ b/sdk/core/src/gateway/gateway_account_esdt_tokens.rs @@ -16,7 +16,7 @@ impl<'a> GetAccountEsdtTokensRequest<'a> { } } -impl<'a> GatewayRequest for GetAccountEsdtTokensRequest<'a> { +impl GatewayRequest for GetAccountEsdtTokensRequest<'_> { type Payload = (); type DecodedJson = EsdtBalanceResponse; type Result = HashMap; diff --git a/sdk/core/src/gateway/gateway_account_storage.rs b/sdk/core/src/gateway/gateway_account_storage.rs index 6c1bffe55f..011d29d460 100644 --- a/sdk/core/src/gateway/gateway_account_storage.rs +++ b/sdk/core/src/gateway/gateway_account_storage.rs @@ -16,7 +16,7 @@ impl<'a> GetAccountStorageRequest<'a> { } } -impl<'a> GatewayRequest for GetAccountStorageRequest<'a> { +impl GatewayRequest for GetAccountStorageRequest<'_> { type Payload = (); type DecodedJson = AccountStorageResponse; type Result = HashMap; diff --git a/sdk/core/src/gateway/gateway_chain_simulator_set_state.rs b/sdk/core/src/gateway/gateway_chain_simulator_set_state.rs new file mode 100644 index 0000000000..284f00a709 --- /dev/null +++ b/sdk/core/src/gateway/gateway_chain_simulator_set_state.rs @@ -0,0 +1,133 @@ +use anyhow::anyhow; +use serde::{Deserialize, Serialize}; +use std::{ + collections::HashMap, + fs::{File, OpenOptions}, + io::{BufReader, BufWriter}, + path::Path, +}; + +use crate::data::account::Account; + +use super::{GatewayRequest, GatewayRequestType, SET_STATE_ENDPOINT}; + +#[derive(Debug, Clone, Serialize, Deserialize)] +pub struct SetStateResponse { + pub data: serde_json::Value, + pub error: String, + pub code: String, +} + +#[derive(Debug, Clone, Serialize, Deserialize, Default)] +pub struct SetStateAccount { + pub address: String, + pub nonce: u64, + pub balance: String, + pub keys: HashMap, + pub code: String, + #[serde(default)] + pub code_hash: String, + #[serde(default)] + pub root_hash: String, + #[serde(default)] + pub code_metadata: String, + #[serde(default)] + pub owner_address: String, + #[serde(default)] + pub developer_reward: String, +} + +impl From for SetStateAccount { + fn from(value: Account) -> Self { + Self { + address: value.address.to_bech32_string().unwrap_or_default(), + nonce: value.nonce, + balance: value.balance.to_string(), + keys: HashMap::new(), + code: value.code, + code_hash: value.code_hash.unwrap_or_default(), + root_hash: value.root_hash.unwrap_or_default(), + code_metadata: value.code_metadata.unwrap_or_default(), + owner_address: value.owner_address.unwrap_or_default(), + developer_reward: value.developer_reward.unwrap_or_default(), + } + } +} + +impl SetStateAccount { + pub fn with_keys(mut self, keys: HashMap) -> Self { + self.keys = keys; + + self + } + + pub fn add_to_state_file(self, path: &Path) { + let mut accounts = if path.exists() { + let file = File::open(path) + .unwrap_or_else(|_| panic!("Failed to open state file at path {path:#?}")); + + let reader = BufReader::new(file); + + serde_json::from_reader::<_, Vec>(reader).unwrap_or_default() + } else { + Vec::new() + }; + + if let Some(existing_account) = accounts + .iter_mut() + .find(|account| account.address == self.address) + { + *existing_account = self; + } else { + accounts.push(self); + } + + let file = OpenOptions::new() + .write(true) + .create(true) + .truncate(true) + .open(path) + .unwrap_or_else(|_| panic!("Failed to open or create state file at path {path:#?}")); + + let writer = BufWriter::new(file); + serde_json::to_writer_pretty(writer, &accounts).unwrap_or_else(|_| { + panic!("Failed to write updated state accounts to file at path {path:#?}") + }); + } +} + +/// Sets state for a list of accounts using the chain simulator API. +pub struct ChainSimulatorSetStateRequest { + pub accounts: Vec, +} + +impl ChainSimulatorSetStateRequest { + pub fn for_accounts(accounts: Vec) -> Self { + Self { accounts } + } +} + +impl GatewayRequest for ChainSimulatorSetStateRequest { + type Payload = Vec; + type DecodedJson = SetStateResponse; + type Result = String; + + fn get_payload(&self) -> Option<&Self::Payload> { + Some(&self.accounts) + } + + fn request_type(&self) -> GatewayRequestType { + GatewayRequestType::Post + } + + fn get_endpoint(&self) -> String { + SET_STATE_ENDPOINT.to_owned() + } + + fn process_json(&self, decoded: Self::DecodedJson) -> anyhow::Result { + match decoded.code.as_str() { + "successful" => Ok(decoded.code), + _ => Err(anyhow!("{}", decoded.error)), + } + } +} diff --git a/sdk/core/src/gateway/gateway_tx_cost.rs b/sdk/core/src/gateway/gateway_tx_cost.rs index 333b0324c5..3ca8eff823 100644 --- a/sdk/core/src/gateway/gateway_tx_cost.rs +++ b/sdk/core/src/gateway/gateway_tx_cost.rs @@ -8,7 +8,7 @@ use super::{GatewayRequest, GatewayRequestType, COST_TRANSACTION_ENDPOINT}; /// Note: it is a POST request. pub struct GetTxCost<'a>(pub &'a Transaction); -impl<'a> GatewayRequest for GetTxCost<'a> { +impl GatewayRequest for GetTxCost<'_> { type Payload = Transaction; type DecodedJson = ResponseTxCost; type Result = TxCostResponseData; diff --git a/sdk/core/src/gateway/gateway_tx_info.rs b/sdk/core/src/gateway/gateway_tx_info.rs index f4d26e9d44..d9cc12d02b 100644 --- a/sdk/core/src/gateway/gateway_tx_info.rs +++ b/sdk/core/src/gateway/gateway_tx_info.rs @@ -27,7 +27,7 @@ impl<'a> GetTxInfo<'a> { } } -impl<'a> GatewayRequest for GetTxInfo<'a> { +impl GatewayRequest for GetTxInfo<'_> { type Payload = (); type DecodedJson = TransactionInfo; type Result = TransactionOnNetwork; diff --git a/sdk/core/src/gateway/gateway_tx_process_status.rs b/sdk/core/src/gateway/gateway_tx_process_status.rs index d829cb60fe..103bb4e4a6 100644 --- a/sdk/core/src/gateway/gateway_tx_process_status.rs +++ b/sdk/core/src/gateway/gateway_tx_process_status.rs @@ -14,7 +14,7 @@ impl<'a> GetTxProcessStatus<'a> { } } -impl<'a> GatewayRequest for GetTxProcessStatus<'a> { +impl GatewayRequest for GetTxProcessStatus<'_> { type Payload = (); type DecodedJson = TransactionProcessStatus; type Result = (String, String); diff --git a/sdk/core/src/gateway/gateway_tx_send.rs b/sdk/core/src/gateway/gateway_tx_send.rs index a76354df8e..4c3b9d584a 100644 --- a/sdk/core/src/gateway/gateway_tx_send.rs +++ b/sdk/core/src/gateway/gateway_tx_send.rs @@ -6,7 +6,7 @@ use super::{GatewayRequest, GatewayRequestType, SEND_TRANSACTION_ENDPOINT}; /// Sends a single transaction. pub struct SendTxRequest<'a>(pub &'a Transaction); -impl<'a> GatewayRequest for SendTxRequest<'a> { +impl GatewayRequest for SendTxRequest<'_> { type Payload = Transaction; type DecodedJson = SendTransactionResponse; type Result = String; diff --git a/sdk/core/src/gateway/gateway_tx_send_multi.rs b/sdk/core/src/gateway/gateway_tx_send_multi.rs index 472beaf5ba..8be1d1d4c0 100644 --- a/sdk/core/src/gateway/gateway_tx_send_multi.rs +++ b/sdk/core/src/gateway/gateway_tx_send_multi.rs @@ -7,7 +7,7 @@ use super::{GatewayRequest, GatewayRequestType, SEND_MULTIPLE_TRANSACTIONS_ENDPO /// Sends multiple transactions at once. pub struct SendMultiTxRequest<'a>(pub &'a [Transaction]); -impl<'a> GatewayRequest for SendMultiTxRequest<'a> { +impl GatewayRequest for SendMultiTxRequest<'_> { type Payload = [Transaction]; type DecodedJson = SendTransactionsResponse; type Result = Vec; diff --git a/sdk/core/src/gateway/gateway_tx_status.rs b/sdk/core/src/gateway/gateway_tx_status.rs index ac4e37e6b4..12660a2c57 100644 --- a/sdk/core/src/gateway/gateway_tx_status.rs +++ b/sdk/core/src/gateway/gateway_tx_status.rs @@ -14,7 +14,7 @@ impl<'a> GetTxStatus<'a> { } } -impl<'a> GatewayRequest for GetTxStatus<'a> { +impl GatewayRequest for GetTxStatus<'_> { type Payload = (); type DecodedJson = TransactionStatus; type Result = String; diff --git a/sdk/core/src/gateway/gateway_tx_vmquery.rs b/sdk/core/src/gateway/gateway_tx_vmquery.rs index e1523571da..9de88f6d2f 100644 --- a/sdk/core/src/gateway/gateway_tx_vmquery.rs +++ b/sdk/core/src/gateway/gateway_tx_vmquery.rs @@ -6,7 +6,7 @@ use super::{GatewayRequest, GatewayRequestType, VM_VALUES_ENDPOINT}; /// Executes a VM query. pub struct VMQueryRequest<'a>(pub &'a VMQueryInput); -impl<'a> GatewayRequest for VMQueryRequest<'a> { +impl GatewayRequest for VMQueryRequest<'_> { type Payload = VMQueryInput; type DecodedJson = ResponseVmValue; type Result = VmValuesResponseData; diff --git a/sdk/core/src/retrieve_tx_on_network.rs b/sdk/core/src/retrieve_tx_on_network.rs index 3cfcf9fc77..3c60a92fa2 100644 --- a/sdk/core/src/retrieve_tx_on_network.rs +++ b/sdk/core/src/retrieve_tx_on_network.rs @@ -138,7 +138,7 @@ pub fn extract_message_from_string_reason(reason: &str) -> String { return message[0].to_string(); } - return contract_error.last().unwrap_or(&"").split(']').collect(); + contract_error.last().unwrap_or(&"").split(']').collect() } fn create_tx_failed(error_message: &str) -> TransactionOnNetwork { diff --git a/sdk/scenario-format/src/value_interpreter/reconstructor.rs b/sdk/scenario-format/src/value_interpreter/reconstructor.rs index 6efacefba4..e21a298905 100644 --- a/sdk/scenario-format/src/value_interpreter/reconstructor.rs +++ b/sdk/scenario-format/src/value_interpreter/reconstructor.rs @@ -147,7 +147,7 @@ fn can_interpret_as_string(bytes: &[u8]) -> bool { if bytes.is_empty() { return false; } - return !bytes.iter().any(|&b| !(32..=126).contains(&b)); + !bytes.iter().any(|&b| !(32..=126).contains(&b)) } fn code_pretty(bytes: &[u8]) -> String { diff --git a/tools/rust-debugger/format-tests/src/format_tests.rs b/tools/rust-debugger/format-tests/src/format_tests.rs index 2c72e4acda..755bbbda17 100644 --- a/tools/rust-debugger/format-tests/src/format_tests.rs +++ b/tools/rust-debugger/format-tests/src/format_tests.rs @@ -181,7 +181,7 @@ fn main() { let invalid_handle = DebugHandle::from(-1000); let biguint_with_invalid_handle: BigUint = - BigUint::from_handle(invalid_handle.clone()); + unsafe { BigUint::from_handle(invalid_handle.clone()) }; push!( to_check, biguint_with_invalid_handle, @@ -189,7 +189,7 @@ fn main() { ); let big_float_with_invalid_handle: BigFloat = - BigFloat::from_handle(invalid_handle.clone()); + unsafe { BigFloat::from_handle(invalid_handle.clone()) }; push!( to_check, big_float_with_invalid_handle, @@ -197,7 +197,7 @@ fn main() { ); let managed_buffer_with_invalid_handle: ManagedBuffer = - ManagedBuffer::from_handle(invalid_handle.clone()); + unsafe { ManagedBuffer::from_handle(invalid_handle.clone()) }; push!( to_check, managed_buffer_with_invalid_handle, @@ -205,7 +205,7 @@ fn main() { ); let token_identifier_with_invalid_handle: TokenIdentifier = - TokenIdentifier::from_handle(invalid_handle.clone()); + unsafe { TokenIdentifier::from_handle(invalid_handle.clone()) }; push!( to_check, token_identifier_with_invalid_handle, @@ -213,7 +213,7 @@ fn main() { ); let optional_value_some_with_invalid_handle: OptionalValue> = - OptionalValue::Some(BigUint::from_handle(invalid_handle.clone())); + OptionalValue::Some(unsafe { BigUint::from_handle(invalid_handle.clone()) }); push!( to_check, optional_value_some_with_invalid_handle,

ManagedVecItemPayloadAdd for P +where + P: ManagedVecItemPayload, { type Output = Self; + + fn split_from_add(payload: &Self::Output) -> (&Self, &ManagedVecItemEmptyPayload) { + (payload, &ManagedVecItemEmptyPayload) + } + + fn split_mut_from_add( + _payload: &mut Self::Output, + ) -> (&mut Self, &mut ManagedVecItemEmptyPayload) { + unimplemented!() + } } /// Replaces a const generic expression. @@ -84,6 +138,38 @@ macro_rules! payload_add { for ManagedVecItemPayloadBuffer<$dec1> { type Output = ManagedVecItemPayloadBuffer<$result_add>; + + fn split_from_add( + payload: &ManagedVecItemPayloadBuffer<$result_add>, + ) -> ( + &ManagedVecItemPayloadBuffer<$dec1>, + &ManagedVecItemPayloadBuffer<$dec2>, + ) { + unsafe { + let ptr1 = payload.buffer.as_ptr(); + let ptr2 = ptr1.add($dec1); + ( + &*ptr1.cast::>(), + &*ptr2.cast::>(), + ) + } + } + + fn split_mut_from_add( + payload: &mut Self::Output, + ) -> ( + &mut ManagedVecItemPayloadBuffer<$dec1>, + &mut ManagedVecItemPayloadBuffer<$dec2>, + ) { + unsafe { + let ptr1 = payload.buffer.as_mut_ptr(); + let ptr2 = ptr1.add($dec1); + ( + &mut *ptr1.cast::>(), + &mut *ptr2.cast::>(), + ) + } + } } }; } 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 new file mode 100644 index 0000000000..f4712e7464 --- /dev/null +++ b/framework/base/src/types/managed/wrapped/managed_vec_iter_owned.rs @@ -0,0 +1,103 @@ +use multiversx_sc_codec::{DecodeError, DecodeErrorHandler, TopDecodeMultiInput}; + +use crate::{ + api::{ErrorApi, ManagedTypeApi}, + types::{ManagedBuffer, ManagedType}, +}; + +use super::{ManagedVec, ManagedVecItem, ManagedVecPayloadIterator}; + +impl IntoIterator for ManagedVec +where + M: ManagedTypeApi, + T: ManagedVecItem, +{ + type Item = T; + type IntoIter = ManagedVecOwnedIterator; + fn into_iter(self) -> Self::IntoIter { + ManagedVecOwnedIterator::new(self) + } +} + +pub struct ManagedVecOwnedIterator +where + M: ManagedTypeApi, + T: ManagedVecItem, +{ + payload_iter: ManagedVecPayloadIterator, +} + +impl ManagedVecOwnedIterator +where + M: ManagedTypeApi, + T: ManagedVecItem, +{ + pub(crate) fn new(managed_vec: ManagedVec) -> Self { + unsafe { + ManagedVecOwnedIterator { + payload_iter: ManagedVecPayloadIterator::new(managed_vec.forget_into_handle()), + } + } + } + + pub(crate) fn iter_is_empty(&self) -> bool { + self.payload_iter.iter_is_empty() + } +} + +impl Iterator for ManagedVecOwnedIterator +where + M: ManagedTypeApi, + T: ManagedVecItem, +{ + type Item = T; + + fn next(&mut self) -> Option { + let payload = self.payload_iter.next()?; + Some(T::read_from_payload(&payload)) + } + + fn size_hint(&self) -> (usize, Option) { + self.payload_iter.size_hint() + } +} + +impl ExactSizeIterator for ManagedVecOwnedIterator +where + M: ManagedTypeApi, + T: ManagedVecItem, +{ +} + +impl DoubleEndedIterator for ManagedVecOwnedIterator +where + M: ManagedTypeApi, + T: ManagedVecItem, +{ + fn next_back(&mut self) -> Option { + let payload = self.payload_iter.next_back()?; + Some(T::read_from_payload(&payload)) + } +} + +impl TopDecodeMultiInput for ManagedVecOwnedIterator> +where + A: ManagedTypeApi + ErrorApi, +{ + type ValueInput = ManagedBuffer; + + fn has_next(&self) -> bool { + !self.iter_is_empty() + } + + fn next_value_input(&mut self, h: H) -> Result + 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 new file mode 100644 index 0000000000..28fd6e3943 --- /dev/null +++ b/framework/base/src/types/managed/wrapped/managed_vec_iter_payload.rs @@ -0,0 +1,114 @@ +use core::marker::PhantomData; + +use crate::api::{ManagedBufferApiImpl, ManagedTypeApi}; + +use super::ManagedVecItemPayload; + +pub struct ManagedVecPayloadIterator +where + M: ManagedTypeApi, + P: ManagedVecItemPayload, +{ + pub(super) vec_handle: M::ManagedBufferHandle, + byte_start: usize, + byte_end: usize, + _phantom: PhantomData