Skip to content

Commit

Permalink
Merge pull request #54 from multiversx/more-multisig-improvements
Browse files Browse the repository at this point in the history
multisig improvements again
  • Loading branch information
dorin-iancu authored Feb 7, 2024
2 parents 23b524f + 0b936d6 commit b9fac79
Show file tree
Hide file tree
Showing 8 changed files with 82 additions and 17 deletions.
1 change: 1 addition & 0 deletions contracts/multisig/scenarios/changeQuorum.scen.json
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,7 @@
"out": [
[
"u32:1",
"u32:0",
"u8:4|u32:3",
"u32:2|address:alice|address:bob"
]
Expand Down
3 changes: 2 additions & 1 deletion contracts/multisig/src/action.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ use multiversx_sc::{
types::{BigUint, CodeMetadata, ManagedAddress, ManagedBuffer, ManagedVec},
};

use crate::multisig_state::ActionId;
use crate::multisig_state::{ActionId, GroupId};

multiversx_sc::derive_imports!();

Expand Down Expand Up @@ -55,6 +55,7 @@ impl<M: ManagedTypeApi> Action<M> {
#[derive(TopEncode, TypeAbi)]
pub struct ActionFullInfo<M: ManagedTypeApi> {
pub action_id: ActionId,
pub group_id: GroupId,
pub action_data: Action<M>,
pub signers: ManagedVec<M, ManagedAddress<M>>,
}
Expand Down
32 changes: 27 additions & 5 deletions contracts/multisig/src/multisig.rs
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ pub trait Multisig:

#[upgrade]
fn upgrade(&self, quorum: usize, board: MultiValueEncoded<ManagedAddress>) {
self.init(quorum, board)
self.init(quorum, board);
}

/// Allows the contract to receive funds even if it is marked as unpayable in the protocol.
Expand All @@ -72,9 +72,11 @@ pub trait Multisig:
action_id,
action_data,
signers: self.get_action_signers(action_id),
group_id: self.group_for_action(action_id).get(),
});
}
}

result
}

Expand All @@ -87,10 +89,10 @@ pub trait Multisig:
fn user_role(&self, user: ManagedAddress) -> UserRole {
let user_id = self.user_mapper().get_user_id(&user);
if user_id == 0 {
UserRole::None
} else {
self.user_id_to_role(user_id).get()
return UserRole::None;
}

self.user_id_to_role(user_id).get()
}

/// Lists all users that can sign actions.
Expand All @@ -117,19 +119,39 @@ pub trait Multisig:
}
}
}

result
}

/// Clears storage pertaining to an action that is no longer supposed to be executed.
/// Any signatures that the action received must first be removed, via `unsign`.
/// Otherwise this endpoint would be prone to abuse.
#[endpoint(discardAction)]
fn discard_action(&self, action_id: ActionId) {
fn discard_action_endpoint(&self, action_id: ActionId) {
let (_, caller_role) = self.get_caller_id_and_role();
require!(
caller_role.can_discard_action(),
"only board members and proposers can discard actions"
);

self.discard_action(action_id);
}

/// Discard all the actions with the given IDs
#[endpoint(discardBatch)]
fn discard_batch(&self, action_ids: MultiValueEncoded<ActionId>) {
let (_, caller_role) = self.get_caller_id_and_role();
require!(
caller_role.can_discard_action(),
"only board members and proposers can discard actions"
);

for action_id in action_ids {
self.discard_action(action_id);
}
}

fn discard_action(&self, action_id: ActionId) {
require!(
self.get_action_valid_signer_count(action_id) == 0,
"cannot discard action with valid signatures"
Expand Down
20 changes: 20 additions & 0 deletions contracts/multisig/src/multisig_perform.rs
Original file line number Diff line number Diff line change
Expand Up @@ -115,13 +115,33 @@ pub trait MultisigPerformModule:
self.perform_action(action_id)
}

/// Perform all the actions with the given IDs
#[endpoint(performBatch)]
fn perform_batch(&self, action_ids: MultiValueEncoded<ActionId>) {
let (_, caller_role) = self.get_caller_id_and_role();
require!(
caller_role.can_perform_action(),
"only board members and proposers can perform actions"
);

for action_id in action_ids {
require!(
self.quorum_reached(action_id),
"quorum has not been reached"
);

let _ = self.perform_action(action_id);
}
}

fn perform_action(&self, action_id: ActionId) -> OptionalValue<ManagedAddress> {
let action = self.action_mapper().get(action_id);

self.start_perform_action_event(&ActionFullInfo {
action_id,
action_data: action.clone(),
signers: self.get_action_signers(action_id),
group_id: self.group_for_action(action_id).get(),
});

// clean up storage
Expand Down
21 changes: 18 additions & 3 deletions contracts/multisig/src/multisig_sign.rs
Original file line number Diff line number Diff line change
Expand Up @@ -58,14 +58,29 @@ pub trait MultisigSignModule:
/// Actions that are left with no valid signatures can be then deleted to free up storage.
#[endpoint]
fn unsign(&self, action_id: ActionId) {
let (caller_id, caller_role) = self.get_caller_id_and_role();
require!(caller_role.can_sign(), "only board members can un-sign");

self.unsign_action(action_id, caller_id);
}

/// Unsign all actions with the given IDs
#[endpoint(unsignBatch)]
fn unsign_batch(&self, action_ids: MultiValueEncoded<ActionId>) {
let (caller_id, caller_role) = self.get_caller_id_and_role();
require!(caller_role.can_sign(), "only board members can un-sign");

for action_id in action_ids {
self.unsign_action(action_id, caller_id);
}
}

fn unsign_action(&self, action_id: ActionId, caller_id: usize) {
require!(
!self.action_mapper().item_is_empty_unchecked(action_id),
"action does not exist"
);

let (caller_id, caller_role) = self.get_caller_id_and_role();
require!(caller_role.can_sign(), "only board members can un-sign");

let _ = self.action_signer_ids(action_id).swap_remove(&caller_id);
}

Expand Down
4 changes: 2 additions & 2 deletions contracts/multisig/tests/multisig_blackbox_test.rs
Original file line number Diff line number Diff line change
Expand Up @@ -377,7 +377,7 @@ fn test_change_quorum() {
state.world.sc_call(
ScCallStep::new()
.from(BOARD_MEMBER_ADDRESS_EXPR)
.call(state.multisig_contract.discard_action(action_id))
.call(state.multisig_contract.discard_action_endpoint(action_id))
.expect(TxExpect::user_error(
"str:cannot discard action with valid signatures",
)),
Expand All @@ -393,7 +393,7 @@ fn test_change_quorum() {
state.world.sc_call(
ScCallStep::new()
.from(BOARD_MEMBER_ADDRESS_EXPR)
.call(state.multisig_contract.discard_action(action_id)),
.call(state.multisig_contract.discard_action_endpoint(action_id)),
);

// try sign discarded action
Expand Down
9 changes: 6 additions & 3 deletions contracts/multisig/wasm-multisig-full/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,9 @@
////////////////////////////////////////////////////

// Init: 1
// Endpoints: 33
// Endpoints: 36
// Async Callback: 1
// Total number of exported functions: 35
// Total number of exported functions: 38

#![no_std]
#![allow(internal_features)]
Expand All @@ -22,7 +22,8 @@ multiversx_sc_wasm_adapter::endpoints! {
init => init
upgrade => upgrade
deposit => deposit
discardAction => discard_action
discardAction => discard_action_endpoint
discardBatch => discard_batch
getQuorum => quorum
getNumBoardMembers => num_board_members
getNumProposers => num_proposers
Expand All @@ -41,9 +42,11 @@ multiversx_sc_wasm_adapter::endpoints! {
signAndPerform => sign_and_perform
signBatchAndPerform => sign_batch_and_perform
unsign => unsign
unsignBatch => unsign_batch
signed => signed
quorumReached => quorum_reached
performAction => perform_action_endpoint
performBatch => perform_batch
dnsRegister => dns_register
getPendingActionFullInfo => get_pending_action_full_info
userRole => user_role
Expand Down
9 changes: 6 additions & 3 deletions contracts/multisig/wasm/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,9 @@
////////////////////////////////////////////////////

// Init: 1
// Endpoints: 25
// Endpoints: 28
// Async Callback: 1
// Total number of exported functions: 27
// Total number of exported functions: 30

#![no_std]
#![allow(internal_features)]
Expand All @@ -22,7 +22,8 @@ multiversx_sc_wasm_adapter::endpoints! {
init => init
upgrade => upgrade
deposit => deposit
discardAction => discard_action
discardAction => discard_action_endpoint
discardBatch => discard_batch
getQuorum => quorum
getNumBoardMembers => num_board_members
getNumProposers => num_proposers
Expand All @@ -41,9 +42,11 @@ multiversx_sc_wasm_adapter::endpoints! {
signAndPerform => sign_and_perform
signBatchAndPerform => sign_batch_and_perform
unsign => unsign
unsignBatch => unsign_batch
signed => signed
quorumReached => quorum_reached
performAction => perform_action_endpoint
performBatch => perform_batch
dnsRegister => dns_register
)
}
Expand Down

0 comments on commit b9fac79

Please sign in to comment.