From a2f48a52b28900ac60e0fbc59274a4930e69cefd Mon Sep 17 00:00:00 2001 From: Mihai Calin Luca Date: Tue, 26 Mar 2024 02:55:53 +0100 Subject: [PATCH 1/6] vault generated proxy in forwarder - except upgrade --- .../composability/forwarder/src/call_async.rs | 55 ++-- .../composability/forwarder/src/call_sync.rs | 103 +++---- .../forwarder/src/call_transf_exec.rs | 47 ++-- .../forwarder/src/contract_change_owner.rs | 13 +- .../forwarder/src/contract_deploy.rs | 41 ++- .../forwarder/src/forwarder_main.rs | 1 + .../forwarder/src/vault_proxy.rs | 253 ++++++++++++++++++ .../composability/vault/sc-config.toml | 1 + .../returns_new_token_identifier.rs | 4 +- 9 files changed, 412 insertions(+), 106 deletions(-) create mode 100644 contracts/feature-tests/composability/forwarder/src/vault_proxy.rs diff --git a/contracts/feature-tests/composability/forwarder/src/call_async.rs b/contracts/feature-tests/composability/forwarder/src/call_async.rs index 8826c2db48..04ba78faab 100644 --- a/contracts/feature-tests/composability/forwarder/src/call_async.rs +++ b/contracts/feature-tests/composability/forwarder/src/call_async.rs @@ -1,3 +1,5 @@ +use crate::vault_proxy; + multiversx_sc::imports!(); multiversx_sc::derive_imports!(); @@ -14,13 +16,11 @@ const PERCENTAGE_TOTAL: u64 = 10_000; // 100% #[multiversx_sc::module] pub trait ForwarderAsyncCallModule { - #[proxy] - fn vault_proxy(&self) -> vault::Proxy; - #[endpoint] fn echo_args_async(&self, to: ManagedAddress, args: MultiValueEncoded) { - self.vault_proxy() - .contract(to) + self.tx() + .to(&to) + .typed(vault_proxy::VaultProxy) .echo_arguments(args) .async_call() .with_callback(self.callbacks().echo_args_callback()) @@ -57,8 +57,9 @@ pub trait ForwarderAsyncCallModule { #[payable("*")] fn forward_async_accept_funds(&self, to: ManagedAddress) { let payment = self.call_value().egld_or_single_esdt(); - self.vault_proxy() - .contract(to) + self.tx() + .to(&to) + .typed(vault_proxy::VaultProxy) .accept_funds() .with_egld_or_single_esdt_transfer(payment) .async_call() @@ -70,8 +71,9 @@ pub trait ForwarderAsyncCallModule { fn forward_async_accept_funds_half_payment(&self, to: ManagedAddress) { let payment = self.call_value().egld_or_single_esdt(); let half_payment = payment.amount / 2u32; - self.vault_proxy() - .contract(to) + self.tx() + .to(&to) + .typed(vault_proxy::VaultProxy) .accept_funds() .with_egld_or_single_esdt_transfer(( payment.token_identifier, @@ -89,8 +91,9 @@ pub trait ForwarderAsyncCallModule { let fees = &payment.amount * &percentage_fees / PERCENTAGE_TOTAL; let amount_to_send = &payment.amount - &fees; - self.vault_proxy() - .contract(to) + self.tx() + .to(&to) + .typed(vault_proxy::VaultProxy) .accept_funds() .with_egld_or_single_esdt_transfer(( payment.token_identifier, @@ -109,8 +112,9 @@ pub trait ForwarderAsyncCallModule { token_nonce: u64, amount: BigUint, ) { - self.vault_proxy() - .contract(to) + self.tx() + .to(&to) + .typed(vault_proxy::VaultProxy) .retrieve_funds(token, token_nonce, amount) .async_call() .with_callback(self.callbacks().retrieve_funds_callback()) @@ -146,16 +150,17 @@ pub trait ForwarderAsyncCallModule { token_identifier: &EgldOrEsdtTokenIdentifier, amount: &BigUint, ) { - self.vault_proxy() - .contract(to.clone()) + self.tx() + .to(to) + .typed(vault_proxy::VaultProxy) .accept_funds() - .with_egld_or_single_esdt_transfer((token_identifier.clone(), 0, amount.clone())) + .with_egld_or_single_esdt_transfer((token_identifier.clone(), 0u64, amount.clone())) .async_call() .with_callback( self.callbacks() .send_funds_twice_callback(to, token_identifier, amount), ) - .call_and_exit() + .call_and_exit(); } #[callback] @@ -165,12 +170,13 @@ pub trait ForwarderAsyncCallModule { token_identifier: &EgldOrEsdtTokenIdentifier, cb_amount: &BigUint, ) { - self.vault_proxy() - .contract(to.clone()) + self.tx() + .to(to) + .typed(vault_proxy::VaultProxy) .accept_funds() - .with_egld_or_single_esdt_transfer((token_identifier.clone(), 0, cb_amount.clone())) + .with_egld_or_single_esdt_transfer((token_identifier.clone(), 0u64, cb_amount.clone())) .async_call() - .call_and_exit() + .call_and_exit(); } #[endpoint] @@ -188,12 +194,13 @@ pub trait ForwarderAsyncCallModule { all_token_payments.push(payment); } - self.vault_proxy() - .contract(to) + self.tx() + .to(&to) + .typed(vault_proxy::VaultProxy) .accept_funds() .with_multi_token_transfer(all_token_payments) .async_call() - .call_and_exit() + .call_and_exit(); } #[view] diff --git a/contracts/feature-tests/composability/forwarder/src/call_sync.rs b/contracts/feature-tests/composability/forwarder/src/call_sync.rs index 67d923936e..d2b32e1913 100644 --- a/contracts/feature-tests/composability/forwarder/src/call_sync.rs +++ b/contracts/feature-tests/composability/forwarder/src/call_sync.rs @@ -1,23 +1,24 @@ +use crate::vault_proxy; + multiversx_sc::imports!(); const PERCENTAGE_TOTAL: u64 = 10_000; // 100% #[multiversx_sc::module] pub trait ForwarderSyncCallModule { - #[proxy] - fn vault_proxy(&self) -> vault::Proxy; - #[endpoint] #[payable("*")] fn echo_arguments_sync(&self, to: ManagedAddress, args: MultiValueEncoded) { let half_gas = self.blockchain().get_gas_left() / 2; - let result: MultiValueEncoded = self - .vault_proxy() - .contract(to) - .echo_arguments(args) + let result = self + .tx() + .to(&to) .with_gas_limit(half_gas) - .execute_on_dest_context(); + .typed(vault_proxy::VaultProxy) + .echo_arguments(args) + .returns(ReturnsExact) + .sync_call(); self.execute_on_dest_context_result_event(&result.into_vec_of_buffers()); } @@ -31,21 +32,25 @@ pub trait ForwarderSyncCallModule { ) { let one_third_gas = self.blockchain().get_gas_left() / 3; - let result: MultiValueEncoded = self - .vault_proxy() - .contract(to.clone()) - .echo_arguments(&args) + let result = self + .tx() + .to(&to) .with_gas_limit(one_third_gas) - .execute_on_dest_context(); + .typed(vault_proxy::VaultProxy) + .echo_arguments(args.clone()) + .returns(ReturnsExact) + .sync_call(); self.execute_on_dest_context_result_event(&result.into_vec_of_buffers()); - let result: MultiValueEncoded = self - .vault_proxy() - .contract(to) - .echo_arguments(&args) + let result = self + .tx() + .to(&to) .with_gas_limit(one_third_gas) - .execute_on_dest_context(); + .typed(vault_proxy::VaultProxy) + .echo_arguments(args) + .returns(ReturnsExact) + .sync_call(); self.execute_on_dest_context_result_event(&result.into_vec_of_buffers()); } @@ -59,13 +64,16 @@ pub trait ForwarderSyncCallModule { let payment = self.call_value().egld_or_single_esdt(); let half_gas = self.blockchain().get_gas_left() / 2; - let result: MultiValue2> = self - .vault_proxy() - .contract(to) + let result = self + .tx() + .to(&to) + .with_gas_limit(half_gas) + .typed(vault_proxy::VaultProxy) .accept_funds_echo_payment() .with_egld_or_single_esdt_transfer(payment) - .with_gas_limit(half_gas) - .execute_on_dest_context(); + .returns(ReturnsExact) + .sync_call(); + let (egld_value, esdt_transfers_multi) = result.into_tuple(); self.accept_funds_sync_result_event(&egld_value, &esdt_transfers_multi); @@ -78,12 +86,13 @@ pub trait ForwarderSyncCallModule { let fees = &payment * &percentage_fees / PERCENTAGE_TOTAL; let amount_to_send = payment - fees; - let () = self - .vault_proxy() - .contract(to) + self.tx() + .to(&to) + .typed(vault_proxy::VaultProxy) .accept_funds() - .with_egld_or_single_esdt_transfer((token_id, 0, amount_to_send)) - .execute_on_dest_context(); + .with_egld_or_single_esdt_transfer((token_id, 0u64, amount_to_send)) + .returns(ReturnsExact) + .sync_call(); } #[event("accept_funds_sync_result")] @@ -97,17 +106,19 @@ pub trait ForwarderSyncCallModule { #[payable("*")] fn forward_sync_accept_funds_then_read(&self, to: ManagedAddress) -> usize { let payment = self.call_value().egld_or_single_esdt(); - self.vault_proxy() - .contract(to.clone()) + self.tx() + .to(&to) + .typed(vault_proxy::VaultProxy) .accept_funds() .with_egld_or_single_esdt_transfer(payment) - .execute_on_dest_context::<()>(); + .sync_call(); - self.vault_proxy() - .contract(to) + self.tx() + .to(&to) + .typed(vault_proxy::VaultProxy) .call_counts(b"accept_funds") - .execute_on_dest_context::>() - .into() + .returns(ReturnsExact) + .sync_call() } #[endpoint] @@ -118,10 +129,11 @@ pub trait ForwarderSyncCallModule { token_nonce: u64, amount: BigUint, ) { - self.vault_proxy() - .contract(to) + self.tx() + .to(&to) + .typed(vault_proxy::VaultProxy) .retrieve_funds(token, token_nonce, amount) - .execute_on_dest_context::<()>(); + .sync_call(); } #[payable("*")] @@ -134,15 +146,16 @@ pub trait ForwarderSyncCallModule { ) { let payments = self.call_value().all_esdt_transfers(); - self.vault_proxy() - .contract(to) + self.tx() + .to(&to) + .typed(vault_proxy::VaultProxy) .retrieve_funds_with_transfer_exec( token, amount, OptionalValue::::Some(b"accept_funds_func".into()), ) .with_multi_token_transfer(payments.clone_value()) - .execute_on_dest_context::<()>(); + .sync_call(); } #[payable("*")] @@ -163,11 +176,11 @@ pub trait ForwarderSyncCallModule { all_token_payments.push(payment); } - let () = self - .vault_proxy() - .contract(to) + self.tx() + .to(&to) + .typed(vault_proxy::VaultProxy) .accept_funds() .with_multi_token_transfer(all_token_payments) - .execute_on_dest_context(); + .sync_call(); } } diff --git a/contracts/feature-tests/composability/forwarder/src/call_transf_exec.rs b/contracts/feature-tests/composability/forwarder/src/call_transf_exec.rs index e402ea5316..3573987867 100644 --- a/contracts/feature-tests/composability/forwarder/src/call_transf_exec.rs +++ b/contracts/feature-tests/composability/forwarder/src/call_transf_exec.rs @@ -1,18 +1,18 @@ +use crate::vault_proxy; + multiversx_sc::imports!(); const PERCENTAGE_TOTAL: u64 = 10_000; // 100% #[multiversx_sc::module] pub trait ForwarderTransferExecuteModule { - #[proxy] - fn vault_proxy(&self) -> vault::Proxy; - #[endpoint] #[payable("*")] fn forward_transf_exec_accept_funds(&self, to: ManagedAddress) { let payment = self.call_value().egld_or_single_esdt(); - self.vault_proxy() - .contract(to) + self.tx() + .to(&to) + .typed(vault_proxy::VaultProxy) .accept_funds() .with_egld_or_single_esdt_transfer(payment) .transfer_execute(); @@ -29,10 +29,11 @@ pub trait ForwarderTransferExecuteModule { let fees = &payment * &percentage_fees / PERCENTAGE_TOTAL; let amount_to_send = payment - fees; - self.vault_proxy() - .contract(to) + self.tx() + .to(&to) + .typed(vault_proxy::VaultProxy) .accept_funds() - .with_egld_or_single_esdt_transfer((token_id, 0, amount_to_send)) + .with_egld_or_single_esdt_transfer((token_id, 0u64, amount_to_send)) .transfer_execute(); } @@ -43,15 +44,17 @@ pub trait ForwarderTransferExecuteModule { let half_payment = payment / 2u32; let half_gas = self.blockchain().get_gas_left() / 2; - self.vault_proxy() - .contract(to.clone()) + self.tx() + .to(&to) + .typed(vault_proxy::VaultProxy) .accept_funds() .with_egld_or_single_esdt_transfer((token.clone(), token_nonce, half_payment.clone())) .with_gas_limit(half_gas) .transfer_execute(); - self.vault_proxy() - .contract(to) + self.tx() + .to(&to) + .typed(vault_proxy::VaultProxy) .accept_funds() .with_egld_or_single_esdt_transfer((token, token_nonce, half_payment)) .with_gas_limit(half_gas) @@ -70,8 +73,9 @@ pub trait ForwarderTransferExecuteModule { let payment_token = payment.token_identifier.clone(); let gas_left_before = self.blockchain().get_gas_left(); - self.vault_proxy() - .contract(to) + self.tx() + .to(&to) + .typed(vault_proxy::VaultProxy) .accept_funds() .with_egld_or_single_esdt_transfer(payment) .transfer_execute(); @@ -102,8 +106,9 @@ pub trait ForwarderTransferExecuteModule { all_token_payments.push(payment); } - self.vault_proxy() - .contract(to) + self.tx() + .to(&to) + .typed(vault_proxy::VaultProxy) .accept_funds() .with_multi_token_transfer(all_token_payments) .transfer_execute() @@ -124,8 +129,9 @@ pub trait ForwarderTransferExecuteModule { all_token_payments.push(payment); } - self.vault_proxy() - .contract(to) + self.tx() + .to(&to) + .typed(vault_proxy::VaultProxy) .accept_funds() .with_multi_token_transfer(all_token_payments) .transfer_execute() @@ -146,8 +152,9 @@ pub trait ForwarderTransferExecuteModule { all_token_payments.push(payment); } - self.vault_proxy() - .contract(to) + self.tx() + .to(&to) + .typed(vault_proxy::VaultProxy) .reject_funds() .with_multi_token_transfer(all_token_payments) .transfer_execute() diff --git a/contracts/feature-tests/composability/forwarder/src/contract_change_owner.rs b/contracts/feature-tests/composability/forwarder/src/contract_change_owner.rs index 8c5a140e8d..2e1247d9f7 100644 --- a/contracts/feature-tests/composability/forwarder/src/contract_change_owner.rs +++ b/contracts/feature-tests/composability/forwarder/src/contract_change_owner.rs @@ -1,10 +1,9 @@ +use crate::vault_proxy; + multiversx_sc::imports!(); #[multiversx_sc::module] pub trait ChangeOwnerModule { - #[proxy] - fn vault_proxy(&self) -> vault::Proxy; - #[endpoint(changeOwnerAddress)] fn change_owner( &self, @@ -20,9 +19,11 @@ pub trait ChangeOwnerModule { } fn get_owner_of_vault_contract(&self, address: ManagedAddress) -> ManagedAddress { - self.vault_proxy() - .contract(address) + self.tx() + .to(&address) + .typed(vault_proxy::VaultProxy) .get_owner_address() - .execute_on_dest_context() + .returns(ReturnsExact) + .sync_call() } } diff --git a/contracts/feature-tests/composability/forwarder/src/contract_deploy.rs b/contracts/feature-tests/composability/forwarder/src/contract_deploy.rs index d573b45ec0..aefdfb55c0 100644 --- a/contracts/feature-tests/composability/forwarder/src/contract_deploy.rs +++ b/contracts/feature-tests/composability/forwarder/src/contract_deploy.rs @@ -1,10 +1,9 @@ +use crate::vault_proxy; + multiversx_sc::imports!(); #[multiversx_sc::module] pub trait DeployContractModule { - #[proxy] - fn vault_proxy(&self) -> vault::Proxy; - #[endpoint] fn deploy_contract( &self, @@ -36,9 +35,22 @@ pub trait DeployContractModule { code: &ManagedBuffer, opt_arg: OptionalValue, ) -> (ManagedAddress, OptionalValue) { - self.vault_proxy() + let (new_address, response_vec) = self + .tx() + .typed(vault_proxy::VaultProxy) .init(opt_arg) - .deploy_contract(code, CodeMetadata::DEFAULT) + .code(code.clone()) + .returns(ReturnsNewAddress) + .returns(ReturnsRaw) + .sync_call(); + + let response = if response_vec.is_empty() { + OptionalValue::None + } else { + OptionalValue::Some(response_vec.get(0).clone_value()) + }; + + (new_address, response) } #[endpoint] @@ -47,9 +59,22 @@ pub trait DeployContractModule { source_address: ManagedAddress, opt_arg: OptionalValue, ) -> MultiValue2> { - self.vault_proxy() + let (new_address, response_vec) = self + .tx() + .typed(vault_proxy::VaultProxy) .init(opt_arg) - .deploy_from_source(&source_address, CodeMetadata::DEFAULT) - .into() + .code_metadata(CodeMetadata::DEFAULT) + .from_source(source_address) + .returns(ReturnsNewAddress) + .returns(ReturnsRaw) + .sync_call(); + + let response = if response_vec.is_empty() { + OptionalValue::None + } else { + OptionalValue::Some(response_vec.get(0).clone_value()) + }; + + MultiValue2::from((new_address, response)) } } diff --git a/contracts/feature-tests/composability/forwarder/src/forwarder_main.rs b/contracts/feature-tests/composability/forwarder/src/forwarder_main.rs index ee8403fd9a..61dcbad468 100644 --- a/contracts/feature-tests/composability/forwarder/src/forwarder_main.rs +++ b/contracts/feature-tests/composability/forwarder/src/forwarder_main.rs @@ -13,6 +13,7 @@ pub mod nft; pub mod roles; pub mod sft; pub mod storage; +pub mod vault_proxy; multiversx_sc::imports!(); diff --git a/contracts/feature-tests/composability/forwarder/src/vault_proxy.rs b/contracts/feature-tests/composability/forwarder/src/vault_proxy.rs new file mode 100644 index 0000000000..f1c9e2127a --- /dev/null +++ b/contracts/feature-tests/composability/forwarder/src/vault_proxy.rs @@ -0,0 +1,253 @@ +//////////////////////////////////////////////////// +////////////////// AUTO-GENERATED ////////////////// +//////////////////////////////////////////////////// + +#![allow(clippy::all)] + +use multiversx_sc::proxy_imports::*; + +pub struct VaultProxy; + +impl TxProxyTrait for VaultProxy +where + Env: TxEnv, + From: TxFrom, + To: TxTo, + Gas: TxGas, +{ + type TxProxyMethods = VaultProxyMethods; + + fn proxy_methods(self, tx: Tx) -> Self::TxProxyMethods { + VaultProxyMethods { wrapped_tx: tx } + } +} + +pub struct VaultProxyMethods +where + Env: TxEnv, + From: TxFrom, + To: TxTo, + Gas: TxGas, +{ + wrapped_tx: Tx, +} + +#[rustfmt::skip] +impl VaultProxyMethods +where + Env: TxEnv, + Env::Api: VMApi, + From: TxFrom, + Gas: TxGas, +{ + pub fn init< + Arg0: CodecInto>>, + >( + self, + opt_arg_to_echo: Arg0, + ) -> TxProxyDeploy>> { + self.wrapped_tx + .raw_deploy() + .argument(&opt_arg_to_echo) + .original_result() + } +} + +#[rustfmt::skip] +impl VaultProxyMethods +where + Env: TxEnv, + Env::Api: VMApi, + From: TxFrom, + To: TxTo, + Gas: TxGas, +{ + pub fn echo_arguments< + Arg0: CodecInto>>, + >( + self, + args: Arg0, + ) -> TxProxyCall>> { + self.wrapped_tx + .raw_call() + .function_name("echo_arguments") + .argument(&args) + .original_result() + } + + pub fn echo_arguments_without_storage< + Arg0: CodecInto>>, + >( + self, + args: Arg0, + ) -> TxProxyCall>> { + self.wrapped_tx + .raw_call() + .function_name("echo_arguments_without_storage") + .argument(&args) + .original_result() + } + + pub fn echo_caller( + self, + ) -> TxProxyCall> { + self.wrapped_tx + .raw_call() + .function_name("echo_caller") + .original_result() + } + + pub fn accept_funds( + self, + ) -> TxProxyCall { + self.wrapped_tx + .raw_call() + .function_name("accept_funds") + .original_result() + } + + pub fn accept_funds_echo_payment( + self, + ) -> TxProxyCall, MultiValueEncoded>>> { + self.wrapped_tx + .raw_call() + .function_name("accept_funds_echo_payment") + .original_result() + } + + pub fn accept_funds_single_esdt_transfer( + self, + ) -> TxProxyCall { + self.wrapped_tx + .raw_call() + .function_name("accept_funds_single_esdt_transfer") + .original_result() + } + + pub fn reject_funds( + self, + ) -> TxProxyCall { + self.wrapped_tx + .raw_call() + .function_name("reject_funds") + .original_result() + } + + pub fn retrieve_funds_with_transfer_exec< + Arg0: CodecInto>, + Arg1: CodecInto>, + Arg2: CodecInto>>, + >( + self, + token: Arg0, + amount: Arg1, + opt_receive_func: Arg2, + ) -> TxProxyCall { + self.wrapped_tx + .raw_call() + .function_name("retrieve_funds_with_transfer_exec") + .argument(&token) + .argument(&amount) + .argument(&opt_receive_func) + .original_result() + } + + pub fn retrieve_funds_promises< + Arg0: CodecInto>, + Arg1: CodecInto>>, + >( + self, + back_transfers: Arg0, + back_transfer_value: Arg1, + ) -> TxProxyCall { + self.wrapped_tx + .raw_call() + .function_name("retrieve_funds_promises") + .argument(&back_transfers) + .argument(&back_transfer_value) + .original_result() + } + + pub fn retrieve_funds< + Arg0: CodecInto>, + Arg1: CodecInto, + Arg2: CodecInto>, + >( + self, + token: Arg0, + nonce: Arg1, + amount: Arg2, + ) -> TxProxyCall { + self.wrapped_tx + .raw_call() + .function_name("retrieve_funds") + .argument(&token) + .argument(&nonce) + .argument(&amount) + .original_result() + } + + pub fn retrieve_multi_funds_async< + Arg0: CodecInto, u64, BigUint>>>, + >( + self, + token_payments: Arg0, + ) -> TxProxyCall { + self.wrapped_tx + .raw_call() + .function_name("retrieve_multi_funds_async") + .argument(&token_payments) + .original_result() + } + + pub fn burn_and_create_retrive_async( + self, + ) -> TxProxyCall { + self.wrapped_tx + .raw_call() + .function_name("burn_and_create_retrive_async") + .original_result() + } + + pub fn get_owner_address( + self, + ) -> TxProxyCall> { + self.wrapped_tx + .raw_call() + .function_name("get_owner_address") + .original_result() + } + + /// We already leave a trace of the calls using the event logs; + /// this additional counter has the role of showing that storage also gets saved correctly. + pub fn call_counts< + Arg0: CodecInto>, + >( + self, + endpoint: Arg0, + ) -> TxProxyCall { + self.wrapped_tx + .raw_call() + .function_name("call_counts") + .argument(&endpoint) + .original_result() + } + + pub fn num_called_retrieve_funds_promises( + self, + ) -> TxProxyCall { + self.wrapped_tx + .raw_call() + .function_name("num_called_retrieve_funds_promises") + .original_result() + } + + pub fn num_async_calls_sent_from_child( + self, + ) -> TxProxyCall { + self.wrapped_tx + .raw_call() + .function_name("num_async_calls_sent_from_child") + .original_result() + } +} diff --git a/contracts/feature-tests/composability/vault/sc-config.toml b/contracts/feature-tests/composability/vault/sc-config.toml index f0d4da2f02..33b8945873 100644 --- a/contracts/feature-tests/composability/vault/sc-config.toml +++ b/contracts/feature-tests/composability/vault/sc-config.toml @@ -1,5 +1,6 @@ [settings] main = "main" +proxy-paths = ["../forwarder/src/vault_proxy.rs"] [contracts.main] name = "vault" diff --git a/framework/base/src/types/interaction/tx_rh_list/returns_new_token_identifier.rs b/framework/base/src/types/interaction/tx_rh_list/returns_new_token_identifier.rs index c1a4af47d1..5e8169df92 100644 --- a/framework/base/src/types/interaction/tx_rh_list/returns_new_token_identifier.rs +++ b/framework/base/src/types/interaction/tx_rh_list/returns_new_token_identifier.rs @@ -3,12 +3,10 @@ use crate::{ proxy_imports::TokenIdentifier, types::{ interaction::tx_call_deploy::RHListItemDeploy, BackTransfers, ManagedAddress, - ManagedBuffer, ManagedVec, RHListItemSync, TxEnv, + ManagedBuffer, ManagedVec, RHListItem, RHListItemSync, TxEnv, }, }; -use super::RHListItem; - pub struct ReturnsNewTokenIdentifier; impl RHListItem for ReturnsNewTokenIdentifier From ba6da3fbe0c034a7b7784c553694b72115d4a04b Mon Sep 17 00:00:00 2001 From: Mihai Calin Luca Date: Tue, 26 Mar 2024 18:40:48 +0100 Subject: [PATCH 2/6] upgrade in proxy --- .../src/forwarder_raw_deploy_upgrade.rs | 4 +- .../forwarder/src/contract_upgrade.rs | 27 ++-- .../forwarder/src/vault_proxy.rs | 22 +++ .../proxy-test-first/src/proxy-test-first.rs | 7 +- framework/base/src/types/interaction/mod.rs | 4 + framework/base/src/types/interaction/tx.rs | 99 +++++++++++++- .../src/types/interaction/tx_call_deploy.rs | 117 +--------------- .../src/types/interaction/tx_call_upgrade.rs | 127 ++++++++++++++++++ .../base/src/types/interaction/tx_proxy.rs | 10 +- .../src/types/interaction/upgrade_call.rs | 90 +++++++++++++ .../generate_proxy/proxy_sc_functions_gen.rs | 69 +++++++++- 11 files changed, 437 insertions(+), 139 deletions(-) create mode 100644 framework/base/src/types/interaction/tx_call_upgrade.rs create mode 100644 framework/base/src/types/interaction/upgrade_call.rs diff --git a/contracts/feature-tests/composability/forwarder-raw/src/forwarder_raw_deploy_upgrade.rs b/contracts/feature-tests/composability/forwarder-raw/src/forwarder_raw_deploy_upgrade.rs index b8fc6138eb..03ebdd9cb4 100644 --- a/contracts/feature-tests/composability/forwarder-raw/src/forwarder_raw_deploy_upgrade.rs +++ b/contracts/feature-tests/composability/forwarder-raw/src/forwarder_raw_deploy_upgrade.rs @@ -48,7 +48,7 @@ pub trait ForwarderRawDeployUpgrade { ) { self.tx() .to(child_sc_address) - .raw_deploy() + .raw_upgrade() .code(new_code) .code_metadata(code_metadata) .arguments_raw(args.to_arg_buffer()) @@ -65,7 +65,7 @@ pub trait ForwarderRawDeployUpgrade { ) { self.tx() .to(sc_address) - .raw_deploy() + .raw_upgrade() .from_source(source_contract_address) .code_metadata(code_metadata) .arguments_raw(args.to_arg_buffer()) diff --git a/contracts/feature-tests/composability/forwarder/src/contract_upgrade.rs b/contracts/feature-tests/composability/forwarder/src/contract_upgrade.rs index b1629eeaa1..a1a402c6e7 100644 --- a/contracts/feature-tests/composability/forwarder/src/contract_upgrade.rs +++ b/contracts/feature-tests/composability/forwarder/src/contract_upgrade.rs @@ -1,10 +1,9 @@ +use crate::vault_proxy; + multiversx_sc::imports!(); #[multiversx_sc::module] pub trait UpgradeContractModule { - #[proxy] - fn vault_proxy(&self, sc_address: ManagedAddress) -> vault::Proxy; - #[endpoint(upgradeVault)] fn upgrade_vault( &self, @@ -12,9 +11,14 @@ pub trait UpgradeContractModule { new_code: ManagedBuffer, opt_arg: OptionalValue, ) { - self.vault_proxy(child_sc_address) - .init(opt_arg) - .upgrade_contract(&new_code, CodeMetadata::UPGRADEABLE); + let _ = self + .tx() + .to(child_sc_address) + .typed(vault_proxy::VaultProxy) + .upgrade(opt_arg) + .code(new_code) + .code_metadata(CodeMetadata::UPGRADEABLE) + .upgrade_async_call(); } #[endpoint] @@ -24,8 +28,13 @@ pub trait UpgradeContractModule { source_address: ManagedAddress, opt_arg: OptionalValue, ) { - self.vault_proxy(child_sc_address) - .init(opt_arg) - .upgrade_from_source(&source_address, CodeMetadata::UPGRADEABLE) + let _ = self + .tx() + .to(child_sc_address) + .typed(vault_proxy::VaultProxy) + .upgrade(opt_arg) + .code_metadata(CodeMetadata::UPGRADEABLE) + .from_source(source_address) + .upgrade_async_call(); } } diff --git a/contracts/feature-tests/composability/forwarder/src/vault_proxy.rs b/contracts/feature-tests/composability/forwarder/src/vault_proxy.rs index f1c9e2127a..2d6cb09693 100644 --- a/contracts/feature-tests/composability/forwarder/src/vault_proxy.rs +++ b/contracts/feature-tests/composability/forwarder/src/vault_proxy.rs @@ -53,6 +53,28 @@ where } } +#[rustfmt::skip] +impl VaultProxyMethods +where + Env: TxEnv, + Env::Api: VMApi, + From: TxFrom, + To: TxTo, + Gas: TxGas, +{ + pub fn upgrade< + Arg0: CodecInto>>, + >( + self, + opt_arg_to_echo: Arg0, + ) -> TxProxyUpgrade, OptionalValue>>> { + self.wrapped_tx + .raw_upgrade() + .argument(&opt_arg_to_echo) + .original_result() + } +} + #[rustfmt::skip] impl VaultProxyMethods where diff --git a/contracts/feature-tests/composability/proxy-test-first/src/proxy-test-first.rs b/contracts/feature-tests/composability/proxy-test-first/src/proxy-test-first.rs index b6d04b7606..7d18e22e3b 100644 --- a/contracts/feature-tests/composability/proxy-test-first/src/proxy-test-first.rs +++ b/contracts/feature-tests/composability/proxy-test-first/src/proxy-test-first.rs @@ -77,10 +77,11 @@ pub trait ProxyTestFirst { let payment = self.call_value().egld_value(); let other_contract = self.get_other_contract(); - self.message_me_proxy() - .init(456) // TODO: upgrade proxy + self.tx() .to(other_contract) - .with_egld_transfer(payment.clone_value()) + .raw_upgrade() + .argument(&456) + .egld(payment.clone_value()) .upgrade_contract(&code, CodeMetadata::UPGRADEABLE); } diff --git a/framework/base/src/types/interaction/mod.rs b/framework/base/src/types/interaction/mod.rs index 7b751e162b..125f16150b 100644 --- a/framework/base/src/types/interaction/mod.rs +++ b/framework/base/src/types/interaction/mod.rs @@ -25,6 +25,7 @@ mod tx_call_async_promises; mod tx_call_deploy; mod tx_call_sync; mod tx_call_te; +mod tx_call_upgrade; mod tx_code_source; mod tx_data; mod tx_env; @@ -38,6 +39,7 @@ mod tx_rh_list; mod tx_rh_original_result; mod tx_to; mod typed_function_call; +mod upgrade_call; pub use annotated::*; pub use async_call::AsyncCall; @@ -63,6 +65,7 @@ pub use tx_call_async::*; pub use tx_call_async_promises::*; pub use tx_call_deploy::*; pub use tx_call_sync::*; +pub use tx_call_upgrade::*; pub use tx_code_source::*; pub use tx_data::*; pub use tx_env::*; @@ -76,5 +79,6 @@ pub use tx_rh_list::*; pub use tx_rh_original_result::*; pub use tx_to::*; pub use typed_function_call::*; +pub use upgrade_call::*; pub type TxScBase = TxBaseWithEnv>; diff --git a/framework/base/src/types/interaction/tx.rs b/framework/base/src/types/interaction/tx.rs index 583e038625..548da703c8 100644 --- a/framework/base/src/types/interaction/tx.rs +++ b/framework/base/src/types/interaction/tx.rs @@ -16,7 +16,7 @@ use super::{ ExplicitGas, FromSource, FunctionCall, ManagedArgBuffer, OriginalResultMarker, RHList, RHListAppendNoRet, RHListAppendRet, RHListItem, TxCodeSource, TxCodeValue, TxData, TxEgldValue, TxEnv, TxFrom, TxFromSourceValue, TxGas, TxPayment, TxPaymentEgldOnly, TxProxyTrait, - TxResultHandler, TxScEnv, TxTo, TxToSpecified, + TxResultHandler, TxScEnv, TxTo, TxToSpecified, UpgradeCall, }; #[must_use] @@ -637,6 +637,74 @@ where } } +impl Tx +where + Env: TxEnv, + From: TxFrom, + To: TxTo, + Payment: TxPaymentEgldOnly, + Gas: TxGas, + RH: TxResultHandler, +{ + pub fn raw_upgrade(self) -> Tx, RH> { + Tx { + env: self.env, + from: self.from, + to: self.to, + payment: self.payment, + gas: self.gas, + data: UpgradeCall::default(), + result_handler: self.result_handler, + } + } +} + +impl Tx, RH> +where + Env: TxEnv, + From: TxFrom, + To: TxTo, + Payment: TxPaymentEgldOnly, + Gas: TxGas, + RH: TxResultHandler, +{ + pub fn code( + self, + code: CodeValue, + ) -> Tx>, RH> + where + CodeValue: TxCodeValue, + { + Tx { + env: self.env, + from: self.from, + to: self.to, + payment: self.payment, + gas: self.gas, + data: self.data.code_source(Code(code)), + result_handler: self.result_handler, + } + } + + pub fn from_source( + self, + source_address: FromSourceValue, + ) -> Tx>, RH> + where + FromSourceValue: TxFromSourceValue, + { + Tx { + env: self.env, + from: self.from, + to: self.to, + payment: self.payment, + gas: self.gas, + data: self.data.code_source(FromSource(source_address)), + result_handler: self.result_handler, + } + } +} + impl Tx, RH> where Env: TxEnv, @@ -712,6 +780,35 @@ where } } +impl + Tx, RH> +where + Env: TxEnv, + From: TxFrom, + To: TxTo, + Payment: TxPaymentEgldOnly, + Gas: TxGas, + CodeSource: TxCodeSource, + RH: TxResultHandler, +{ + pub fn code_metadata(mut self, code_metadata: CodeMetadata) -> Self { + self.data = self.data.code_metadata(code_metadata); + self + } + + #[inline] + pub fn argument(mut self, arg: &T) -> Self { + self.data = self.data.argument(arg); + self + } + + #[inline] + pub fn arguments_raw(mut self, raw: ManagedArgBuffer) -> Self { + self.data.arg_buffer = raw; + self + } +} + impl From< Tx< diff --git a/framework/base/src/types/interaction/tx_call_deploy.rs b/framework/base/src/types/interaction/tx_call_deploy.rs index c5f948ea32..0fd9cedc74 100644 --- a/framework/base/src/types/interaction/tx_call_deploy.rs +++ b/framework/base/src/types/interaction/tx_call_deploy.rs @@ -10,7 +10,7 @@ use crate::{ use super::{ contract_call_exec::decode_result, Code, ConsNoRet, ConsRet, DeployCall, FromSource, OriginalResultMarker, RHList, RHListExec, RHListItem, Tx, TxCodeValue, TxEmptyResultHandler, - TxEnv, TxFromSourceValue, TxGas, TxPaymentEgldOnly, TxResultHandler, TxScEnv, + TxEnv, TxFromSourceValue, TxGas, TxPaymentEgldOnly, TxResultHandler, TxScEnv, UpgradeCall, }; pub struct DeployRawResult @@ -141,70 +141,6 @@ where } } -impl - Tx< - TxScEnv, - (), - ManagedAddress, - Payment, - Gas, - DeployCall, Code>, - RH, - > -where - Api: CallTypeApi, - Payment: TxPaymentEgldOnly>, - Gas: TxGas>, - CodeValue: TxCodeValue>, - RH: TxEmptyResultHandler>, -{ - pub fn upgrade_async_call(self) { - let gas = self.gas.explicit_or_gas_left(&self.env); - self.payment.with_egld_value(|egld_value| { - SendRawWrapper::::new().upgrade_contract( - &self.to, - gas, - egld_value, - &self.data.code_source.0.into_value(&self.env), - self.data.code_metadata, - &self.data.arg_buffer, - ); - }); - } -} - -impl - Tx< - TxScEnv, - (), - ManagedAddress, - Payment, - Gas, - DeployCall, FromSource>, - RH, - > -where - Api: CallTypeApi, - Payment: TxPaymentEgldOnly>, - Gas: TxGas>, - FromSourceValue: TxFromSourceValue>, - RH: TxEmptyResultHandler>, -{ - pub fn upgrade_async_call(self) { - let gas = self.gas.explicit_or_gas_left(&self.env); - self.payment.with_egld_value(|egld_value| { - SendRawWrapper::::new().upgrade_from_source_contract( - &self.to, - gas, - egld_value, - &self.data.code_source.0.into_value(&self.env), - self.data.code_metadata, - &self.data.arg_buffer, - ); - }); - } -} - impl Tx< TxScEnv, @@ -263,54 +199,3 @@ where (new_address, decode_result(raw_results)) } } - -impl - Tx, (), ManagedAddress, Payment, Gas, DeployCall, ()>, RH> -where - Api: CallTypeApi, - Payment: TxPaymentEgldOnly>, - Gas: TxGas>, - RH: TxEmptyResultHandler>, -{ - /// Backwards compatibility, immitates the old API. - /// - /// Note that the data type (the `DeployCall`) doesn't have the code set. - /// This is because the old API was passing it as paramter, so we do the Apime here. - /// For clarity, we don't want it set twice. - pub fn upgrade_contract(self, code: &ManagedBuffer, code_metadata: CodeMetadata) { - let gas = self.gas.explicit_or_gas_left(&self.env); - self.payment.with_egld_value(|egld_value| { - SendRawWrapper::::new().upgrade_contract( - &self.to, - gas, - egld_value, - code, - code_metadata, - &self.data.arg_buffer, - ); - }); - } - - /// Backwards compatibility, immitates the old API. - /// - /// Note that the data type (the `DeployCall`) doesn't have the code set. - /// This is because the old API was passing it as paramter, so we do the Apime here. - /// For clarity, we don't want it set twice. - pub fn upgrade_from_source( - self, - source_address: &ManagedAddress, - code_metadata: CodeMetadata, - ) { - let gas = self.gas.explicit_or_gas_left(&self.env); - self.payment.with_egld_value(|egld_value| { - SendRawWrapper::::new().upgrade_from_source_contract( - &self.to, - gas, - egld_value, - source_address, - code_metadata, - &self.data.arg_buffer, - ); - }); - } -} diff --git a/framework/base/src/types/interaction/tx_call_upgrade.rs b/framework/base/src/types/interaction/tx_call_upgrade.rs new file mode 100644 index 0000000000..013c5adf06 --- /dev/null +++ b/framework/base/src/types/interaction/tx_call_upgrade.rs @@ -0,0 +1,127 @@ +use crate::{ + api::CallTypeApi, + contract_base::SendRawWrapper, + proxy_imports::{CodeMetadata, ManagedAddress, ManagedBuffer, ManagedVec}, + tuple_util::NestedTupleFlatten, +}; + +use super::{ + tx_from, Code, DeployRawResult, FromSource, RHListExec, Tx, TxCodeValue, TxEmptyResultHandler, + TxFrom, TxFromSourceValue, TxGas, TxPaymentEgldOnly, TxResultHandler, TxScEnv, TxTo, + UpgradeCall, +}; + +impl + Tx< + TxScEnv, + (), + ManagedAddress, + Payment, + Gas, + UpgradeCall, Code>, + RH, + > +where + Api: CallTypeApi, + Payment: TxPaymentEgldOnly>, + Gas: TxGas>, + CodeValue: TxCodeValue>, + RH: TxEmptyResultHandler>, +{ + pub fn upgrade_async_call(self) { + let gas = self.gas.explicit_or_gas_left(&self.env); + self.payment.with_egld_value(|egld_value| { + SendRawWrapper::::new().upgrade_contract( + &self.to, + gas, + egld_value, + &self.data.code_source.0.into_value(&self.env), + self.data.code_metadata, + &self.data.arg_buffer, + ); + }); + } +} + +impl + Tx< + TxScEnv, + (), + ManagedAddress, + Payment, + Gas, + UpgradeCall, FromSource>, + RH, + > +where + Api: CallTypeApi, + Payment: TxPaymentEgldOnly>, + Gas: TxGas>, + FromSourceValue: TxFromSourceValue>, + RH: TxEmptyResultHandler>, +{ + pub fn upgrade_async_call(self) { + let gas = self.gas.explicit_or_gas_left(&self.env); + self.payment.with_egld_value(|egld_value| { + SendRawWrapper::::new().upgrade_from_source_contract( + &self.to, + gas, + egld_value, + &self.data.code_source.0.into_value(&self.env), + self.data.code_metadata, + &self.data.arg_buffer, + ); + }); + } +} + +impl + Tx, (), ManagedAddress, Payment, Gas, UpgradeCall, ()>, RH> +where + Api: CallTypeApi, + Payment: TxPaymentEgldOnly>, + Gas: TxGas>, + RH: TxEmptyResultHandler>, +{ + /// Backwards compatibility, immitates the old API. + /// + /// Note that the data type (the `DeployCall`) doesn't have the code set. + /// This is because the old API was passing it as paramter, so we do the Apime here. + /// For clarity, we don't want it set twice. + pub fn upgrade_contract(self, code: &ManagedBuffer, code_metadata: CodeMetadata) { + let gas = self.gas.explicit_or_gas_left(&self.env); + self.payment.with_egld_value(|egld_value| { + SendRawWrapper::::new().upgrade_contract( + &self.to, + gas, + egld_value, + code, + code_metadata, + &self.data.arg_buffer, + ); + }); + } + + /// Backwards compatibility, immitates the old API. + /// + /// Note that the data type (the `DeployCall`) doesn't have the code set. + /// This is because the old API was passing it as paramter, so we do the Apime here. + /// For clarity, we don't want it set twice. + pub fn upgrade_from_source( + self, + source_address: &ManagedAddress, + code_metadata: CodeMetadata, + ) { + let gas = self.gas.explicit_or_gas_left(&self.env); + self.payment.with_egld_value(|egld_value| { + SendRawWrapper::::new().upgrade_from_source_contract( + &self.to, + gas, + egld_value, + source_address, + code_metadata, + &self.data.arg_buffer, + ); + }); + } +} diff --git a/framework/base/src/types/interaction/tx_proxy.rs b/framework/base/src/types/interaction/tx_proxy.rs index f38e356be0..7bb0c67439 100644 --- a/framework/base/src/types/interaction/tx_proxy.rs +++ b/framework/base/src/types/interaction/tx_proxy.rs @@ -1,4 +1,6 @@ -use super::{DeployCall, FunctionCall, OriginalResultMarker, Tx, TxEnv, TxFrom, TxGas, TxTo}; +use super::{ + DeployCall, FunctionCall, OriginalResultMarker, Tx, TxEnv, TxFrom, TxGas, TxTo, UpgradeCall, +}; /// Defines a proxy object for a smart contract. pub trait TxProxyTrait @@ -14,10 +16,14 @@ where fn proxy_methods(self, tx: Tx) -> Self::TxProxyMethods; } -/// Alias for a `Tx` generated from a proxy, in `init` or `upgrade`. +/// Alias for a `Tx` generated from a proxy, in `init`. pub type TxProxyDeploy = Tx, OriginalResultMarker>; /// Alias for a `Tx` generated from a proxy, in an endpoint. pub type TxProxyCall = Tx::Api>, OriginalResultMarker>; + +/// Alias for a `Tx` generated from a proxy, in `upgrade`. +pub type TxProxyUpgrade = + Tx, OriginalResultMarker>; diff --git a/framework/base/src/types/interaction/upgrade_call.rs b/framework/base/src/types/interaction/upgrade_call.rs new file mode 100644 index 0000000000..d69895f029 --- /dev/null +++ b/framework/base/src/types/interaction/upgrade_call.rs @@ -0,0 +1,90 @@ +use multiversx_sc_codec::TopEncodeMulti; + +use crate::types::{CodeMetadata, ManagedBuffer, ManagedBufferCachedBuilder}; + +use super::{ManagedArgBuffer, TxCodeSource, TxData, TxEnv}; + +/// Holds deploy data: code, code metadata, and arguments. +pub struct UpgradeCall +where + Env: TxEnv, + CodeSource: TxCodeSource, +{ + pub code_source: CodeSource, + pub code_metadata: CodeMetadata, + pub arg_buffer: ManagedArgBuffer, +} + +impl Default for UpgradeCall +where + Env: TxEnv, +{ + fn default() -> UpgradeCall { + UpgradeCall { + code_source: (), + code_metadata: CodeMetadata::DEFAULT, + arg_buffer: ManagedArgBuffer::new(), + } + } +} + +impl TxData for UpgradeCall +where + Env: TxEnv, + CodeSource: TxCodeSource, +{ + fn is_no_call(&self) -> bool { + false + } + + fn to_call_data_string(&self) -> ManagedBuffer { + // Implement as needed for deployment-specific data + let result = ManagedBufferCachedBuilder::default(); + // result.append_managed_buffer(&self.code); + // Add other fields as needed + result.into_managed_buffer() + } +} + +impl UpgradeCall +where + Env: TxEnv, +{ + pub fn code_source(self, code_source: CodeSource) -> UpgradeCall + where + CodeSource: TxCodeSource, + { + UpgradeCall { + code_source, + code_metadata: self.code_metadata, + arg_buffer: self.arg_buffer, + } + } +} + +impl UpgradeCall +where + Env: TxEnv, + CodeSource: TxCodeSource, +{ + pub fn code_metadata(mut self, code_metadata: CodeMetadata) -> Self + where + CodeSource: TxCodeSource, + { + self.code_metadata = code_metadata; + self + } + + /// Adds an argument of any serializable type. + /// + /// Multi-values are accepted. No type checking performed. + pub fn argument(mut self, arg: &T) -> Self { + self.arg_buffer.push_multi_arg(arg); + self + } + + pub fn arguments_raw(mut self, raw: ManagedArgBuffer) -> Self { + self.arg_buffer = raw; + self + } +} diff --git a/framework/meta/src/cmd/contract/generate_proxy/proxy_sc_functions_gen.rs b/framework/meta/src/cmd/contract/generate_proxy/proxy_sc_functions_gen.rs index 59624f979d..54eee5c44a 100644 --- a/framework/meta/src/cmd/contract/generate_proxy/proxy_sc_functions_gen.rs +++ b/framework/meta/src/cmd/contract/generate_proxy/proxy_sc_functions_gen.rs @@ -14,6 +14,19 @@ pub(crate) fn write_content(file: &mut File, abi: ContractAbi) { write_constructor_content(file, constructor_abi.inputs); write_end_of_function(file); } + + writeln!(file, "}}").unwrap(); + + write_header_impl_upgrade_constructor(file, &abi.name); + for (i, upgrade_abi) in abi.upgrade_constructors.clone().into_iter().enumerate() { + if i > 0 { + writeln!(file).unwrap(); + } + write_upgrade_constructor_header(file, upgrade_abi.clone()); + write_upgrade_constructor_content(file, upgrade_abi.inputs); + write_end_of_function(file); + } + writeln!(file, "}}").unwrap(); write_header_impl_endpoints(file, &abi.name); @@ -46,6 +59,24 @@ where .unwrap(); } +fn write_header_impl_upgrade_constructor(file: &mut File, name: &str) { + let proxy_methods_type_name = proxy_methods_type_name(name); + writeln!( + file, + r#" +#[rustfmt::skip] +impl {proxy_methods_type_name} +where + Env: TxEnv, + Env::Api: VMApi, + From: TxFrom, + To: TxTo, + Gas: TxGas, +{{"# + ) + .unwrap(); +} + fn write_header_impl_endpoints(file: &mut File, name: &str) { let proxy_methods_type_name = proxy_methods_type_name(name); writeln!( @@ -64,14 +95,19 @@ where .unwrap(); } -fn write_constructor_header(file: &mut File, contructor_abi: EndpointAbi) { - write_fn_signature(file, contructor_abi.clone()); - write_constructor_output(file, contructor_abi.outputs); +fn write_constructor_header(file: &mut File, constructor_abi: EndpointAbi) { + write_fn_signature(file, constructor_abi.clone()); + write_constructor_output(file, constructor_abi.outputs); } -fn write_endpoint_header(file: &mut File, contructor_abi: EndpointAbi) { - write_fn_signature(file, contructor_abi.clone()); - write_endpoint_output(file, contructor_abi.outputs); +fn write_upgrade_constructor_header(file: &mut File, upgrade_constructor_abi: EndpointAbi) { + write_fn_signature(file, upgrade_constructor_abi.clone()); + write_upgrade_constructor_output(file, upgrade_constructor_abi.outputs); +} + +fn write_endpoint_header(file: &mut File, constructor_abi: EndpointAbi) { + write_fn_signature(file, constructor_abi.clone()); + write_endpoint_output(file, constructor_abi.outputs); } fn write_fn_signature(file: &mut File, endpoint_abi: EndpointAbi) { @@ -98,6 +134,14 @@ fn write_constructor_output(file: &mut File, outputs: Vec) { writeln!(file, "> {{").unwrap(); } +fn write_upgrade_constructor_output(file: &mut File, outputs: Vec) { + write!(file, "-> TxProxyUpgrade {{").unwrap(); +} + fn write_endpoint_output(file: &mut File, outputs: Vec) { write!(file, "-> TxProxyCall) { writeln!(file, " .original_result()").unwrap(); } +fn write_upgrade_constructor_content(file: &mut File, inputs: Vec) { + writeln!( + file, + " self.wrapped_tx + .raw_upgrade()" + ) + .unwrap(); + for input in inputs.iter() { + writeln!(file, " .argument(&{})", input.arg_name).unwrap(); + } + writeln!(file, " .original_result()").unwrap(); +} + fn write_endpoint_content(file: &mut File, function_name: String, inputs: Vec) { writeln!( file, From f4c6c0c104af78c1b56c7f6eff27ee3016788bb4 Mon Sep 17 00:00:00 2001 From: Andrei Marinica Date: Wed, 27 Mar 2024 05:06:00 +0200 Subject: [PATCH 3/6] forwarder cleanup --- .../forwarder/src/contract_deploy.rs | 31 +++++-------------- .../tx_result_handler/returns_result.rs | 19 ++++++++---- 2 files changed, 20 insertions(+), 30 deletions(-) diff --git a/contracts/feature-tests/composability/forwarder/src/contract_deploy.rs b/contracts/feature-tests/composability/forwarder/src/contract_deploy.rs index d3c92f81a7..30bc967665 100644 --- a/contracts/feature-tests/composability/forwarder/src/contract_deploy.rs +++ b/contracts/feature-tests/composability/forwarder/src/contract_deploy.rs @@ -35,22 +35,13 @@ pub trait DeployContractModule { code: &ManagedBuffer, opt_arg: OptionalValue, ) -> (ManagedAddress, OptionalValue) { - let (new_address, response_vec) = self - .tx() + self.tx() .typed(vault_proxy::VaultProxy) .init(opt_arg) .code(code.clone()) .returns(ReturnsNewAddress) - .returns(ReturnsRawResult) - .sync_call(); - - let response = if response_vec.is_empty() { - OptionalValue::None - } else { - OptionalValue::Some(response_vec.get(0).clone_value()) - }; - - (new_address, response) + .returns(ReturnsResult) + .sync_call() } #[endpoint] @@ -59,22 +50,14 @@ pub trait DeployContractModule { source_address: ManagedAddress, opt_arg: OptionalValue, ) -> MultiValue2> { - let (new_address, response_vec) = self - .tx() + self.tx() .typed(vault_proxy::VaultProxy) .init(opt_arg) .code_metadata(CodeMetadata::DEFAULT) .from_source(source_address) .returns(ReturnsNewAddress) - .returns(ReturnsRawResult) - .sync_call(); - - let response = if response_vec.is_empty() { - OptionalValue::None - } else { - OptionalValue::Some(response_vec.get(0).clone_value()) - }; - - MultiValue2::from((new_address, response)) + .returns(ReturnsResult) + .sync_call() + .into() } } diff --git a/framework/base/src/types/interaction/tx_result_handler/returns_result.rs b/framework/base/src/types/interaction/tx_result_handler/returns_result.rs index 71cbd020cf..5082a6bff6 100644 --- a/framework/base/src/types/interaction/tx_result_handler/returns_result.rs +++ b/framework/base/src/types/interaction/tx_result_handler/returns_result.rs @@ -1,11 +1,8 @@ use multiversx_sc_codec::TopDecodeMulti; -use crate::{ - proxy_imports::SyncCallRawResult, - types::{ - interaction::contract_call_exec::decode_result, ManagedBuffer, ManagedVec, RHListItem, - RHListItemExec, TxEnv, - }, +use crate::types::{ + interaction::contract_call_exec::decode_result, DeployRawResult, ManagedBuffer, ManagedVec, + RHListItem, RHListItemExec, SyncCallRawResult, TxEnv, }; /// Indicates that result will be returned. @@ -29,3 +26,13 @@ where decode_result::(raw_result.0.clone()) } } + +impl RHListItemExec, Env, Original> for ReturnsResult +where + Env: TxEnv, + Original: TopDecodeMulti, +{ + fn item_process_result(self, raw_result: &DeployRawResult) -> Original { + decode_result::(raw_result.raw_results.clone()) + } +} From cd557953cb1258428e24d19828b235f8c66f890f Mon Sep 17 00:00:00 2001 From: Andrei Marinica Date: Wed, 27 Mar 2024 05:21:15 +0200 Subject: [PATCH 4/6] vault proxy fix --- .../composability/forwarder/src/vault_proxy.rs | 5 ++++- framework/base/src/abi/type_abi_impl_basic.rs | 11 +++++------ .../contract/generate_proxy/proxy_sc_functions_gen.rs | 2 +- 3 files changed, 10 insertions(+), 8 deletions(-) diff --git a/contracts/feature-tests/composability/forwarder/src/vault_proxy.rs b/contracts/feature-tests/composability/forwarder/src/vault_proxy.rs index 2d6cb09693..f04735e6a5 100644 --- a/contracts/feature-tests/composability/forwarder/src/vault_proxy.rs +++ b/contracts/feature-tests/composability/forwarder/src/vault_proxy.rs @@ -1,7 +1,10 @@ +// Code generated by the multiversx-sc proxy generator. DO NOT EDIT. + //////////////////////////////////////////////////// ////////////////// AUTO-GENERATED ////////////////// //////////////////////////////////////////////////// +#![allow(dead_code)] #![allow(clippy::all)] use multiversx_sc::proxy_imports::*; @@ -67,7 +70,7 @@ where >( self, opt_arg_to_echo: Arg0, - ) -> TxProxyUpgrade, OptionalValue>>> { + ) -> TxProxyUpgrade>>> { self.wrapped_tx .raw_upgrade() .argument(&opt_arg_to_echo) diff --git a/framework/base/src/abi/type_abi_impl_basic.rs b/framework/base/src/abi/type_abi_impl_basic.rs index c14447b2ba..0487e19392 100644 --- a/framework/base/src/abi/type_abi_impl_basic.rs +++ b/framework/base/src/abi/type_abi_impl_basic.rs @@ -113,24 +113,23 @@ impl TypeAbi for String { } } -impl TypeAbi for &str { +impl TypeAbi for &'static str { fn type_name() -> TypeName { - TypeName::type_name() + String::type_name() } fn type_name_rust() -> TypeName { - // we need to convert to an owned type - "Box".into() + "&'static str".into() } } impl TypeAbi for Box { fn type_name() -> TypeName { - TypeName::type_name() + String::type_name() } fn type_name_rust() -> TypeName { - TypeName::type_name_rust() + "Box".into() } } diff --git a/framework/meta/src/cmd/contract/generate_proxy/proxy_sc_functions_gen.rs b/framework/meta/src/cmd/contract/generate_proxy/proxy_sc_functions_gen.rs index 54eee5c44a..00ec38b490 100644 --- a/framework/meta/src/cmd/contract/generate_proxy/proxy_sc_functions_gen.rs +++ b/framework/meta/src/cmd/contract/generate_proxy/proxy_sc_functions_gen.rs @@ -167,7 +167,7 @@ fn write_upgrade_constructor_content(file: &mut File, inputs: Vec) { writeln!( file, " self.wrapped_tx - .raw_upgrade()" + .raw_upgrade()" ) .unwrap(); for input in inputs.iter() { From a0beddf1da2449d4ee4bdb3823d4989aae660f44 Mon Sep 17 00:00:00 2001 From: Andrei Marinica Date: Wed, 27 Mar 2024 05:37:51 +0200 Subject: [PATCH 5/6] rename: upgrade_async_call_and_exit --- .../forwarder-raw/src/forwarder_raw_deploy_upgrade.rs | 4 ++-- .../composability/forwarder/src/contract_upgrade.rs | 10 ++++------ .../base/src/types/interaction/tx_call_upgrade.rs | 10 ++++++++-- 3 files changed, 14 insertions(+), 10 deletions(-) diff --git a/contracts/feature-tests/composability/forwarder-raw/src/forwarder_raw_deploy_upgrade.rs b/contracts/feature-tests/composability/forwarder-raw/src/forwarder_raw_deploy_upgrade.rs index 07ddea1c3a..acd385db2c 100644 --- a/contracts/feature-tests/composability/forwarder-raw/src/forwarder_raw_deploy_upgrade.rs +++ b/contracts/feature-tests/composability/forwarder-raw/src/forwarder_raw_deploy_upgrade.rs @@ -52,7 +52,7 @@ pub trait ForwarderRawDeployUpgrade { .code(new_code) .code_metadata(code_metadata) .arguments_raw(args.to_arg_buffer()) - .upgrade_async_call(); + .upgrade_async_call_and_exit(); } #[endpoint] @@ -70,6 +70,6 @@ pub trait ForwarderRawDeployUpgrade { .code_metadata(code_metadata) .arguments_raw(args.to_arg_buffer()) .with_gas_limit(self.blockchain().get_gas_left()) - .upgrade_async_call(); + .upgrade_async_call_and_exit(); } } diff --git a/contracts/feature-tests/composability/forwarder/src/contract_upgrade.rs b/contracts/feature-tests/composability/forwarder/src/contract_upgrade.rs index a1a402c6e7..f4782821e0 100644 --- a/contracts/feature-tests/composability/forwarder/src/contract_upgrade.rs +++ b/contracts/feature-tests/composability/forwarder/src/contract_upgrade.rs @@ -11,14 +11,13 @@ pub trait UpgradeContractModule { new_code: ManagedBuffer, opt_arg: OptionalValue, ) { - let _ = self - .tx() + self.tx() .to(child_sc_address) .typed(vault_proxy::VaultProxy) .upgrade(opt_arg) .code(new_code) .code_metadata(CodeMetadata::UPGRADEABLE) - .upgrade_async_call(); + .upgrade_async_call_and_exit(); } #[endpoint] @@ -28,13 +27,12 @@ pub trait UpgradeContractModule { source_address: ManagedAddress, opt_arg: OptionalValue, ) { - let _ = self - .tx() + self.tx() .to(child_sc_address) .typed(vault_proxy::VaultProxy) .upgrade(opt_arg) .code_metadata(CodeMetadata::UPGRADEABLE) .from_source(source_address) - .upgrade_async_call(); + .upgrade_async_call_and_exit(); } } diff --git a/framework/base/src/types/interaction/tx_call_upgrade.rs b/framework/base/src/types/interaction/tx_call_upgrade.rs index 013c5adf06..93104a0f08 100644 --- a/framework/base/src/types/interaction/tx_call_upgrade.rs +++ b/framework/base/src/types/interaction/tx_call_upgrade.rs @@ -28,7 +28,10 @@ where CodeValue: TxCodeValue>, RH: TxEmptyResultHandler>, { - pub fn upgrade_async_call(self) { + /// Launches the upgrade async call. + /// + /// TODO: change return type to `!`. + pub fn upgrade_async_call_and_exit(self) { let gas = self.gas.explicit_or_gas_left(&self.env); self.payment.with_egld_value(|egld_value| { SendRawWrapper::::new().upgrade_contract( @@ -60,7 +63,10 @@ where FromSourceValue: TxFromSourceValue>, RH: TxEmptyResultHandler>, { - pub fn upgrade_async_call(self) { + /// Launches the upgrade from source async call. + /// + /// TODO: change return type to `!`. + pub fn upgrade_async_call_and_exit(self) { let gas = self.gas.explicit_or_gas_left(&self.env); self.payment.with_egld_value(|egld_value| { SendRawWrapper::::new().upgrade_from_source_contract( From 8a0c266dbaba3a6da22cbcf8b8e647ed0ea17452 Mon Sep 17 00:00:00 2001 From: Andrei Marinica Date: Wed, 27 Mar 2024 05:47:13 +0200 Subject: [PATCH 6/6] doc fix --- .../base/src/types/interaction/tx_call_deploy.rs | 12 ++++++++---- .../src/types/interaction/tx_call_upgrade.rs | 16 ++++++++++------ 2 files changed, 18 insertions(+), 10 deletions(-) diff --git a/framework/base/src/types/interaction/tx_call_deploy.rs b/framework/base/src/types/interaction/tx_call_deploy.rs index 0fd9cedc74..1b41ccb406 100644 --- a/framework/base/src/types/interaction/tx_call_deploy.rs +++ b/framework/base/src/types/interaction/tx_call_deploy.rs @@ -160,8 +160,10 @@ where /// Backwards compatibility, immitates the old API. /// /// Note that the data type (the `DeployCall`) doesn't have the code set. - /// This is because the old API was passing it as paramter, so we do the Apime here. - /// For clarity, we don't want it set twice. + /// This is because the old API was passing it as paramter, so we use it from the `code` argument. + /// + /// Also note that the code metadata is taken from the `code_metadata` argument. + /// If another one was previously set in the `Tx` object, that one will be ignored. pub fn deploy_contract( self, code: &ManagedBuffer, @@ -181,8 +183,10 @@ where /// Backwards compatibility, immitates the old API. /// /// Note that the data type (the `DeployCall`) doesn't have the code set. - /// This is because the old API was passing it as paramter, so we do the Apime here. - /// For clarity, we don't want it set twice. + /// This is because the old API was passing it as paramter, so we use it from the `code` argument. + /// + /// Also note that the code metadata is taken from the `code_metadata` argument. + /// If another one was previously set in the `Tx` object, that one will be ignored. pub fn deploy_from_source( self, source_address: &ManagedAddress, diff --git a/framework/base/src/types/interaction/tx_call_upgrade.rs b/framework/base/src/types/interaction/tx_call_upgrade.rs index 93104a0f08..2d6af25fab 100644 --- a/framework/base/src/types/interaction/tx_call_upgrade.rs +++ b/framework/base/src/types/interaction/tx_call_upgrade.rs @@ -91,9 +91,11 @@ where { /// Backwards compatibility, immitates the old API. /// - /// Note that the data type (the `DeployCall`) doesn't have the code set. - /// This is because the old API was passing it as paramter, so we do the Apime here. - /// For clarity, we don't want it set twice. + /// Note that the data type (the `UpgradeCall`) doesn't have the code set. + /// This is because the old API was passing it as paramter, so we use it from the `code` argument. + /// + /// Also note that the code metadata is taken from the `code_metadata` argument. + /// If another one was previously set in the `Tx` object, that one will be ignored. pub fn upgrade_contract(self, code: &ManagedBuffer, code_metadata: CodeMetadata) { let gas = self.gas.explicit_or_gas_left(&self.env); self.payment.with_egld_value(|egld_value| { @@ -110,9 +112,11 @@ where /// Backwards compatibility, immitates the old API. /// - /// Note that the data type (the `DeployCall`) doesn't have the code set. - /// This is because the old API was passing it as paramter, so we do the Apime here. - /// For clarity, we don't want it set twice. + /// Note that the data type (the `UpgradeCall`) doesn't have the code set. + /// This is because the old API was passing it as paramter, so we use it from the `code` argument. + /// + /// Also note that the code metadata is taken from the `code_metadata` argument. + /// If another one was previously set in the `Tx` object, that one will be ignored. pub fn upgrade_from_source( self, source_address: &ManagedAddress,