diff --git a/contracts/multisig/src/action.rs b/contracts/multisig/src/action.rs index 9364fdd1..0b5f0510 100644 --- a/contracts/multisig/src/action.rs +++ b/contracts/multisig/src/action.rs @@ -54,6 +54,7 @@ pub enum Action { code_metadata: CodeMetadata, arguments: ManagedVec>, }, + SendSyncCall(CallActionData), } impl Action { diff --git a/contracts/multisig/src/multisig_events.rs b/contracts/multisig/src/multisig_events.rs index a691a99e..4e06f390 100644 --- a/contracts/multisig/src/multisig_events.rs +++ b/contracts/multisig/src/multisig_events.rs @@ -85,4 +85,15 @@ pub trait MultisigEventsModule { #[indexed] gas: GasLimit, #[indexed] arguments: &MultiValueManagedVec, ); + + #[event("performSyncCall")] + fn perform_sync_call_event( + &self, + #[indexed] action_id: ActionId, + #[indexed] to: &ManagedAddress, + #[indexed] egld_value: &BigUint, + #[indexed] gas: GasLimit, + #[indexed] endpoint: &ManagedBuffer, + #[indexed] arguments: &MultiValueManagedVec, + ); } diff --git a/contracts/multisig/src/multisig_perform.rs b/contracts/multisig/src/multisig_perform.rs index 4e3d0007..884d9a74 100644 --- a/contracts/multisig/src/multisig_perform.rs +++ b/contracts/multisig/src/multisig_perform.rs @@ -210,10 +210,12 @@ pub trait MultisigPerformModule: self.quorum().get() <= self.num_board_members().get(), "quorum cannot exceed board size" ); + OptionalValue::None } Action::RemoveUser(user_address) => { self.change_user_role(action_id, user_address, UserRole::None); + let num_board_members = self.num_board_members().get(); let num_proposers = self.num_proposers().get(); require!( @@ -224,6 +226,7 @@ pub trait MultisigPerformModule: self.quorum().get() <= num_board_members, "quorum cannot exceed board size" ); + OptionalValue::None } Action::ChangeQuorum(new_quorum) => { @@ -233,6 +236,7 @@ pub trait MultisigPerformModule: ); self.quorum().set(new_quorum); self.perform_change_quorum_event(action_id, new_quorum); + OptionalValue::None } Action::SendTransferExecuteEgld(call_data) => { @@ -329,6 +333,7 @@ pub trait MultisigPerformModule: code_metadata, &arguments.into(), ); + OptionalValue::Some(new_address) } Action::SCUpgradeFromSource { @@ -356,6 +361,30 @@ pub trait MultisigPerformModule: code_metadata, &arguments.into(), ); + + OptionalValue::None + } + Action::SendSyncCall(call_data) => { + let gas = call_data + .opt_gas_limit + .unwrap_or_else(|| self.ensure_and_get_gas_for_transfer_exec()); + self.perform_sync_call_event( + action_id, + &call_data.to, + &call_data.egld_amount, + gas, + &call_data.endpoint_name, + call_data.arguments.as_multi(), + ); + + let (_, _transfers): (IgnoreValue, _) = self + .send() + .contract_call::<()>(call_data.to, call_data.endpoint_name) + .with_egld_transfer(call_data.egld_amount) + .with_raw_arguments(call_data.arguments.into()) + .with_gas_limit(gas) + .execute_on_dest_context_with_back_transfers(); + OptionalValue::None } } diff --git a/contracts/multisig/src/multisig_propose.rs b/contracts/multisig/src/multisig_propose.rs index bb242f7a..11ff51a0 100644 --- a/contracts/multisig/src/multisig_propose.rs +++ b/contracts/multisig/src/multisig_propose.rs @@ -102,7 +102,7 @@ pub trait MultisigProposeModule: crate::multisig_state::MultisigStateModule { self.propose_action(Action::SendTransferExecuteEsdt(call_data)) } - /// Propose a transaction in which the contract will perform an async call call. + /// Propose a transaction in which the contract will perform an async call. /// Can call smart contract endpoints directly. /// Can use ESDTTransfer/ESDTNFTTransfer/MultiESDTTransfer to send tokens, while also optionally calling endpoints. /// Works well with builtin functions. @@ -165,6 +165,35 @@ pub trait MultisigProposeModule: crate::multisig_state::MultisigStateModule { }) } + /// Propose a transaction in which the contract will perform a sync call. + /// Can call smart contract endpoints directly. + /// Can use ESDTTransfer/ESDTNFTTransfer/MultiESDTTransfer to send tokens, while also optionally calling endpoints. + /// Works well with builtin functions. + /// Cannot simply send EGLD directly without calling anything. + #[endpoint(proposeSyncCall)] + fn propose_sync_call( + &self, + to: ManagedAddress, + egld_amount: BigUint, + opt_gas_limit: Option, + function_call: FunctionCall, + ) -> ActionId { + require!( + egld_amount > 0 || !function_call.is_empty(), + "proposed action has no effect" + ); + + let call_data = CallActionData { + to, + egld_amount, + opt_gas_limit, + endpoint_name: function_call.function_name, + arguments: function_call.arg_buffer.into_vec_of_buffers(), + }; + + self.propose_action(Action::SendSyncCall(call_data)) + } + #[endpoint(proposeBatch)] fn propose_batch(&self, actions: MultiValueEncoded>) -> GroupId { let group_id = self.last_action_group_id().get() + 1; diff --git a/contracts/multisig/wasm-multisig-full/src/lib.rs b/contracts/multisig/wasm-multisig-full/src/lib.rs index 4667340e..9b9a76af 100644 --- a/contracts/multisig/wasm-multisig-full/src/lib.rs +++ b/contracts/multisig/wasm-multisig-full/src/lib.rs @@ -6,9 +6,9 @@ // Init: 1 // Upgrade: 1 -// Endpoints: 40 +// Endpoints: 41 // Async Callback: 1 -// Total number of exported functions: 43 +// Total number of exported functions: 44 #![no_std] @@ -39,6 +39,7 @@ multiversx_sc_wasm_adapter::endpoints! { proposeAsyncCall => propose_async_call proposeSCDeployFromSource => propose_sc_deploy_from_source proposeSCUpgradeFromSource => propose_sc_upgrade_from_source + proposeSyncCall => propose_sync_call proposeBatch => propose_batch sign => sign signBatch => sign_batch diff --git a/contracts/multisig/wasm/src/lib.rs b/contracts/multisig/wasm/src/lib.rs index 18577a71..7fcc512f 100644 --- a/contracts/multisig/wasm/src/lib.rs +++ b/contracts/multisig/wasm/src/lib.rs @@ -6,9 +6,9 @@ // Init: 1 // Upgrade: 1 -// Endpoints: 32 +// Endpoints: 33 // Async Callback: 1 -// Total number of exported functions: 35 +// Total number of exported functions: 36 #![no_std] @@ -39,6 +39,7 @@ multiversx_sc_wasm_adapter::endpoints! { proposeAsyncCall => propose_async_call proposeSCDeployFromSource => propose_sc_deploy_from_source proposeSCUpgradeFromSource => propose_sc_upgrade_from_source + proposeSyncCall => propose_sync_call proposeBatch => propose_batch sign => sign signBatch => sign_batch