pallet_governance/
voting.rs1use polkadot_sdk::frame_support::{dispatch::DispatchResult, ensure};
2
3use crate::{proposal::ProposalStatus, AccountIdOf, Error, Event, Proposals};
4
5pub fn add_vote<T: crate::Config>(
7 voter: AccountIdOf<T>,
8 proposal_id: u64,
9 agree: bool,
10) -> DispatchResult {
11 let Some(mut proposal) = Proposals::<T>::get(proposal_id) else {
12 return Err(Error::<T>::ProposalNotFound.into());
13 };
14
15 let crate::proposal::ProposalStatus::Open {
16 votes_for,
17 votes_against,
18 ..
19 } = &mut proposal.status
20 else {
21 return Err(Error::<T>::ProposalClosed.into());
22 };
23
24 ensure!(
25 !votes_for.contains(&voter) && !votes_against.contains(&voter),
26 crate::Error::<T>::AlreadyVoted
27 );
28
29 let voter_delegated_stake = pallet_torus0::stake::sum_staked_by::<T>(&voter);
30 let voter_owned_stake = pallet_torus0::stake::sum_staking_to::<T>(&voter);
31
32 ensure!(
33 voter_delegated_stake > 0 || voter_owned_stake > 0,
34 crate::Error::<T>::InsufficientStake
35 );
36
37 if !crate::NotDelegatingVotingPower::<T>::get().contains(&voter) && voter_delegated_stake == 0 {
38 return Err(Error::<T>::VoterIsDelegatingVotingPower.into());
39 }
40
41 if agree {
42 votes_for
43 .try_insert(voter.clone())
44 .map_err(|_| Error::<T>::InternalError)?;
45 } else {
46 votes_against
47 .try_insert(voter.clone())
48 .map_err(|_| Error::<T>::InternalError)?;
49 }
50
51 Proposals::<T>::insert(proposal.id, proposal);
52 crate::Pallet::<T>::deposit_event(Event::<T>::ProposalVoted(proposal_id, voter, agree));
53 Ok(())
54}
55
56pub fn remove_vote<T: crate::Config>(voter: AccountIdOf<T>, proposal_id: u64) -> DispatchResult {
58 let Ok(mut proposal) = Proposals::<T>::try_get(proposal_id) else {
59 return Err(Error::<T>::ProposalNotFound.into());
60 };
61
62 let ProposalStatus::Open {
63 votes_for,
64 votes_against,
65 ..
66 } = &mut proposal.status
67 else {
68 return Err(Error::<T>::ProposalClosed.into());
69 };
70
71 let removed = votes_for.remove(&voter) || votes_against.remove(&voter);
72
73 ensure!(removed, crate::Error::<T>::NotVoted);
75
76 Proposals::<T>::insert(proposal.id, proposal);
78 crate::Pallet::<T>::deposit_event(Event::<T>::ProposalVoteUnregistered(proposal_id, voter));
79 Ok(())
80}
81
82pub fn enable_delegation<T: crate::Config>(delegator: AccountIdOf<T>) -> DispatchResult {
84 crate::NotDelegatingVotingPower::<T>::mutate(|delegators| {
85 delegators.remove(&delegator);
86 });
87
88 Ok(())
89}
90
91pub fn disable_delegation<T: crate::Config>(delegator: AccountIdOf<T>) -> DispatchResult {
93 crate::NotDelegatingVotingPower::<T>::mutate(|delegators| {
94 delegators
95 .try_insert(delegator.clone())
96 .map(|_| ())
97 .map_err(|_| Error::<T>::InternalError.into())
98 })
99}