Skip to content

Commit

Permalink
feat(pallet-communities): implement remove_vote
Browse files Browse the repository at this point in the history
  • Loading branch information
pandres95 committed Mar 4, 2024
1 parent c1df84b commit 46c17f2
Show file tree
Hide file tree
Showing 4 changed files with 169 additions and 0 deletions.
28 changes: 28 additions & 0 deletions pallets/communities/src/functions.rs
Original file line number Diff line number Diff line change
Expand Up @@ -139,6 +139,34 @@ impl<T: Config> Pallet<T> {
})
}

pub(crate) fn do_remove_vote(
who: &AccountIdOf<T>,
community_id: &CommunityIdOf<T>,
poll_index: PollIndexOf<T>,
) -> DispatchResult {
T::Polls::try_access_poll(poll_index, |poll_status| {
if let Some((tally, class)) = poll_status.ensure_ongoing() {
ensure!(community_id == &class, Error::<T>::InvalidTrack);
let vote = Self::community_vote_of(who, poll_index).ok_or(Error::<T>::NoVoteCasted)?;

tally.remove_vote(vote.clone().into(), vote.clone().into());

let reason = HoldReason::VoteCasted(poll_index).into();
CommunityVotes::<T>::remove(who, poll_index);

match vote {
Vote::AssetBalance(_, asset_id, amount) => {
T::Assets::release(asset_id.clone(), &reason, who, amount, Precision::BestEffort).map(|_| ())
}
Vote::NativeBalance(..) => T::Balances::thaw(&reason, who),
_ => Ok(()),
}
} else {
Err(Error::<T>::NotOngoing.into())
}
})
}

fn do_lock_for_vote(who: &AccountIdOf<T>, poll_index: &PollIndexOf<T>, vote: &VoteOf<T>) -> DispatchResult {
let reason = HoldReason::VoteCasted(*poll_index).into();
CommunityVotes::<T>::insert(who.clone(), poll_index, vote.clone());
Expand Down
17 changes: 17 additions & 0 deletions pallets/communities/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -353,6 +353,9 @@ pub mod pallet {
/// The vote type does not correspond with the community's selected
/// [`DecisionMethod`][`origin::DecisionMethod`]
InvalidVoteType,
/// The signer tried to remove a vote from a poll they haven't
/// casted a vote yet, or they have already removed it from.
NoVoteCasted,
/// The poll
NoLocksInPlace,
}
Expand Down Expand Up @@ -537,6 +540,20 @@ pub mod pallet {

///
#[pallet::call_index(8)]
pub fn remove_vote(
origin: OriginFor<T>,
membership_id: MembershipIdOf<T>,
#[pallet::compact] poll_index: PollIndexOf<T>,
) -> DispatchResult {
let who = ensure_signed(origin)?;
let _info = T::MemberMgmt::get_membership(membership_id.clone(), &who).ok_or(Error::<T>::NotAMember)?;
let community_id = CommunityIdOf::<T>::from(membership_id);

Self::do_remove_vote(&who, &community_id, poll_index)
}

///
#[pallet::call_index(9)]
pub fn unlock(origin: OriginFor<T>, #[pallet::compact] poll_index: PollIndexOf<T>) -> DispatchResult {
let who = ensure_signed(origin)?;
ensure!(T::Polls::as_ongoing(poll_index).is_none(), Error::<T>::AlreadyOngoing);
Expand Down
101 changes: 101 additions & 0 deletions pallets/communities/src/tests/governance.rs
Original file line number Diff line number Diff line change
Expand Up @@ -835,6 +835,107 @@ mod vote {
}
}

mod remove_vote {
use frame_support::traits::{fungible::Inspect, Polling};

use super::*;

#[test]
fn fails_if_not_a_member() {
new_test_ext().execute_with(|| {
assert_noop!(
Communities::remove_vote(RuntimeOrigin::signed(BOB), MembershipId(COMMUNITY_A, 2), 0,),
Error::NotAMember
);
});
}

#[test]
fn fails_if_trying_to_remove_vote_from_invalid_track() {
new_test_ext().execute_with(|| {
assert_noop!(
Communities::remove_vote(RuntimeOrigin::signed(ALICE), MembershipId(COMMUNITY_A, 1), 1),
Error::InvalidTrack
);
});
}

#[test]
fn fails_if_poll_is_no_vote_casted() {
new_test_ext().execute_with(|| {
assert_noop!(
Communities::remove_vote(RuntimeOrigin::signed(ALICE), MembershipId(COMMUNITY_A, 1), 0),
Error::NoVoteCasted
);
});
}

#[test]
fn it_works() {
new_test_ext().execute_with(|| {
assert_ok!(Communities::vote(
RuntimeOrigin::signed(ALICE),
MembershipId(COMMUNITY_A, 1),
0,
Vote::Standard(true)
));

tick_block();

assert_ok!(Communities::remove_vote(
RuntimeOrigin::signed(ALICE),
MembershipId(COMMUNITY_A, 1),
0
));

assert_eq!(
Referenda::as_ongoing(0).expect("we already created poll 0; qed").0,
Tally::default()
);
});

new_test_ext().execute_with(|| {
assert_ok!(Communities::vote(
RuntimeOrigin::signed(ALICE),
MembershipId(COMMUNITY_C, 1),
2,
Vote::NativeBalance(true, 15)
));

assert_eq!(
Balances::reducible_balance(
&ALICE,
frame_support::traits::tokens::Preservation::Expendable,
frame_support::traits::tokens::Fortitude::Polite
),
0
);

tick_block();

assert_ok!(Communities::remove_vote(
RuntimeOrigin::signed(ALICE),
MembershipId(COMMUNITY_C, 1),
2
));

assert_eq!(
Referenda::as_ongoing(2).expect("we already created poll 2; qed").0,
Tally::default()
);

assert_eq!(
Balances::reducible_balance(
&ALICE,
frame_support::traits::tokens::Preservation::Expendable,
frame_support::traits::tokens::Fortitude::Polite
),
7
);
});
}
}

mod unlock {
use super::*;

Expand Down
23 changes: 23 additions & 0 deletions pallets/communities/src/weights.rs
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@ pub trait WeightInfo {
fn remove_member() -> Weight;
fn set_decision_method () -> Weight;
fn vote() -> Weight;
fn remove_vote() -> Weight;
fn unlock() -> Weight;
}

Expand Down Expand Up @@ -136,6 +137,17 @@ impl<T: frame_system::Config> WeightInfo for SubstrateWeight<T> {
.saturating_add(RocksDbWeight::get().writes(1_u64))
}

/// Storage: Communities Something (r:0 w:1)
/// Proof: Communities Something (max_values: Some(1), max_size: Some(4), added: 499, mode: MaxEncodedLen)
fn remove_vote() -> Weight {
// Proof Size summary in bytes:
// Measured: `0`
// Estimated: `0`
// Minimum execution time: 8_000_000 picoseconds.
Weight::from_parts(9_000_000, 0)
.saturating_add(RocksDbWeight::get().writes(1_u64))
}

/// Storage: Communities Something (r:0 w:1)
/// Proof: Communities Something (max_values: Some(1), max_size: Some(4), added: 499, mode: MaxEncodedLen)
fn unlock() -> Weight {
Expand Down Expand Up @@ -238,6 +250,17 @@ impl WeightInfo for () {
.saturating_add(RocksDbWeight::get().writes(1_u64))
}

/// Storage: Communities Something (r:0 w:1)
/// Proof: Communities Something (max_values: Some(1), max_size: Some(4), added: 499, mode: MaxEncodedLen)
fn remove_vote() -> Weight {
// Proof Size summary in bytes:
// Measured: `0`
// Estimated: `0`
// Minimum execution time: 8_000_000 picoseconds.
Weight::from_parts(9_000_000, 0)
.saturating_add(RocksDbWeight::get().writes(1_u64))
}

/// Storage: Communities Something (r:0 w:1)
/// Proof: Communities Something (max_values: Some(1), max_size: Some(4), added: 499, mode: MaxEncodedLen)
fn unlock() -> Weight {
Expand Down

0 comments on commit 46c17f2

Please sign in to comment.