Skip to content
This repository was archived by the owner on Nov 15, 2023. It is now read-only.

Commit 22d40c7

Browse files
shawntabrizigavofyork
authored andcommitted
Tidy Democracy (#10867)
* add test * Assorted refactorings * complete test * saturating math * final check * use `default` Co-authored-by: Gav Wood <[email protected]>
1 parent 27b8806 commit 22d40c7

File tree

3 files changed

+79
-13
lines changed

3 files changed

+79
-13
lines changed

frame/democracy/src/lib.rs

Lines changed: 31 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -842,7 +842,12 @@ pub mod pallet {
842842

843843
<NextExternal<T>>::kill();
844844
let now = <frame_system::Pallet<T>>::block_number();
845-
Self::inject_referendum(now + voting_period, proposal_hash, threshold, delay);
845+
Self::inject_referendum(
846+
now.saturating_add(voting_period),
847+
proposal_hash,
848+
threshold,
849+
delay,
850+
);
846851
Ok(())
847852
}
848853

@@ -871,7 +876,8 @@ pub mod pallet {
871876
existing_vetoers.binary_search(&who).err().ok_or(Error::<T>::AlreadyVetoed)?;
872877

873878
existing_vetoers.insert(insert_position, who.clone());
874-
let until = <frame_system::Pallet<T>>::block_number() + T::CooloffPeriod::get();
879+
let until =
880+
<frame_system::Pallet<T>>::block_number().saturating_add(T::CooloffPeriod::get());
875881
<Blacklist<T>>::insert(&proposal_hash, (until, existing_vetoers));
876882

877883
Self::deposit_event(Event::<T>::Vetoed { who, proposal_hash, until });
@@ -1089,7 +1095,10 @@ pub mod pallet {
10891095
let now = <frame_system::Pallet<T>>::block_number();
10901096
let (voting, enactment) = (T::VotingPeriod::get(), T::EnactmentPeriod::get());
10911097
let additional = if who == provider { Zero::zero() } else { enactment };
1092-
ensure!(now >= since + voting + additional, Error::<T>::TooEarly);
1098+
ensure!(
1099+
now >= since.saturating_add(voting).saturating_add(additional),
1100+
Error::<T>::TooEarly
1101+
);
10931102
ensure!(expiry.map_or(true, |e| now > e), Error::<T>::Imminent);
10941103

10951104
let res =
@@ -1282,7 +1291,7 @@ impl<T: Config> Pallet<T> {
12821291
/// Get the amount locked in support of `proposal`; `None` if proposal isn't a valid proposal
12831292
/// index.
12841293
pub fn backing_for(proposal: PropIndex) -> Option<BalanceOf<T>> {
1285-
Self::deposit_of(proposal).map(|(l, d)| d * (l.len() as u32).into())
1294+
Self::deposit_of(proposal).map(|(l, d)| d.saturating_mul((l.len() as u32).into()))
12861295
}
12871296

12881297
/// Get all referenda ready for tally at block `n`.
@@ -1318,7 +1327,7 @@ impl<T: Config> Pallet<T> {
13181327
delay: T::BlockNumber,
13191328
) -> ReferendumIndex {
13201329
<Pallet<T>>::inject_referendum(
1321-
<frame_system::Pallet<T>>::block_number() + T::VotingPeriod::get(),
1330+
<frame_system::Pallet<T>>::block_number().saturating_add(T::VotingPeriod::get()),
13221331
proposal_hash,
13231332
threshold,
13241333
delay,
@@ -1424,7 +1433,9 @@ impl<T: Config> Pallet<T> {
14241433
},
14251434
Some(ReferendumInfo::Finished { end, approved }) => {
14261435
if let Some((lock_periods, balance)) = votes[i].1.locked_if(approved) {
1427-
let unlock_at = end + T::VoteLockingPeriod::get() * lock_periods.into();
1436+
let unlock_at = end.saturating_add(
1437+
T::VoteLockingPeriod::get().saturating_mul(lock_periods.into()),
1438+
);
14281439
let now = frame_system::Pallet::<T>::block_number();
14291440
if now < unlock_at {
14301441
ensure!(
@@ -1513,9 +1524,16 @@ impl<T: Config> Pallet<T> {
15131524
};
15141525
sp_std::mem::swap(&mut old, voting);
15151526
match old {
1516-
Voting::Delegating { balance, target, conviction, delegations, prior, .. } => {
1527+
Voting::Delegating {
1528+
balance, target, conviction, delegations, mut prior, ..
1529+
} => {
15171530
// remove any delegation votes to our current target.
15181531
Self::reduce_upstream_delegation(&target, conviction.votes(balance));
1532+
let now = frame_system::Pallet::<T>::block_number();
1533+
let lock_periods = conviction.lock_periods().into();
1534+
let unlock_block = now
1535+
.saturating_add(T::VoteLockingPeriod::get().saturating_mul(lock_periods));
1536+
prior.accumulate(unlock_block, balance);
15191537
voting.set_common(delegations, prior);
15201538
},
15211539
Voting::Direct { votes, delegations, prior } => {
@@ -1548,7 +1566,9 @@ impl<T: Config> Pallet<T> {
15481566
Self::reduce_upstream_delegation(&target, conviction.votes(balance));
15491567
let now = frame_system::Pallet::<T>::block_number();
15501568
let lock_periods = conviction.lock_periods().into();
1551-
prior.accumulate(now + T::VoteLockingPeriod::get() * lock_periods, balance);
1569+
let unlock_block = now
1570+
.saturating_add(T::VoteLockingPeriod::get().saturating_mul(lock_periods));
1571+
prior.accumulate(unlock_block, balance);
15521572
voting.set_common(delegations, prior);
15531573

15541574
Ok(votes)
@@ -1607,7 +1627,7 @@ impl<T: Config> Pallet<T> {
16071627
LastTabledWasExternal::<T>::put(true);
16081628
Self::deposit_event(Event::<T>::ExternalTabled);
16091629
Self::inject_referendum(
1610-
now + T::VotingPeriod::get(),
1630+
now.saturating_add(T::VotingPeriod::get()),
16111631
proposal,
16121632
threshold,
16131633
T::EnactmentPeriod::get(),
@@ -1639,7 +1659,7 @@ impl<T: Config> Pallet<T> {
16391659
depositors,
16401660
});
16411661
Self::inject_referendum(
1642-
now + T::VotingPeriod::get(),
1662+
now.saturating_add(T::VotingPeriod::get()),
16431663
proposal,
16441664
VoteThreshold::SuperMajorityApprove,
16451665
T::EnactmentPeriod::get(),
@@ -1693,7 +1713,7 @@ impl<T: Config> Pallet<T> {
16931713
if status.delay.is_zero() {
16941714
let _ = Self::do_enact_proposal(status.proposal_hash, index);
16951715
} else {
1696-
let when = now + status.delay;
1716+
let when = now.saturating_add(status.delay);
16971717
// Note that we need the preimage now.
16981718
Preimages::<T>::mutate_exists(
16991719
&status.proposal_hash,

frame/democracy/src/tests/delegation.rs

Lines changed: 40 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -158,7 +158,7 @@ fn conviction_should_be_honored_in_delegation() {
158158
// If transactor voted, delegated vote is overwritten.
159159
new_test_ext().execute_with(|| {
160160
let r = begin_referendum();
161-
// Delegate, undelegate and vote.
161+
// Delegate and vote.
162162
assert_ok!(Democracy::delegate(Origin::signed(2), 1, Conviction::Locked6x, 20));
163163
assert_ok!(Democracy::vote(Origin::signed(1), r, aye(1)));
164164
// Delegated vote is huge.
@@ -177,3 +177,42 @@ fn split_vote_delegation_should_be_ignored() {
177177
assert_eq!(tally(r), Tally { ayes: 1, nays: 0, turnout: 10 });
178178
});
179179
}
180+
181+
#[test]
182+
fn redelegation_keeps_lock() {
183+
// If transactor voted, delegated vote is overwritten.
184+
new_test_ext().execute_with(|| {
185+
let r = begin_referendum();
186+
// Delegate and vote.
187+
assert_ok!(Democracy::delegate(Origin::signed(2), 1, Conviction::Locked6x, 20));
188+
assert_ok!(Democracy::vote(Origin::signed(1), r, aye(1)));
189+
// Delegated vote is huge.
190+
assert_eq!(tally(r), Tally { ayes: 121, nays: 0, turnout: 30 });
191+
192+
let mut prior_lock = vote::PriorLock::default();
193+
194+
// Locked balance of delegator exists
195+
assert_eq!(VotingOf::<Test>::get(2).locked_balance(), 20);
196+
assert_eq!(VotingOf::<Test>::get(2).prior(), &prior_lock);
197+
198+
// Delegate someone else at a lower conviction and amount
199+
assert_ok!(Democracy::delegate(Origin::signed(2), 3, Conviction::None, 10));
200+
201+
// 6x prior should appear w/ locked balance.
202+
prior_lock.accumulate(98, 20);
203+
assert_eq!(VotingOf::<Test>::get(2).prior(), &prior_lock);
204+
assert_eq!(VotingOf::<Test>::get(2).locked_balance(), 20);
205+
// Unlock shouldn't work
206+
assert_ok!(Democracy::unlock(Origin::signed(2), 2));
207+
assert_eq!(VotingOf::<Test>::get(2).prior(), &prior_lock);
208+
assert_eq!(VotingOf::<Test>::get(2).locked_balance(), 20);
209+
210+
fast_forward_to(100);
211+
212+
// Now unlock can remove the prior lock and reduce the locked amount.
213+
assert_eq!(VotingOf::<Test>::get(2).prior(), &prior_lock);
214+
assert_ok!(Democracy::unlock(Origin::signed(2), 2));
215+
assert_eq!(VotingOf::<Test>::get(2).prior(), &vote::PriorLock::default());
216+
assert_eq!(VotingOf::<Test>::get(2).locked_balance(), 10);
217+
});
218+
}

frame/democracy/src/vote.rs

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -183,7 +183,7 @@ impl<Balance: Saturating + Ord + Zero + Copy, BlockNumber: Ord + Copy + Zero, Ac
183183
match self {
184184
Voting::Direct { votes, prior, .. } =>
185185
votes.iter().map(|i| i.1.balance()).fold(prior.locked(), |a, i| a.max(i)),
186-
Voting::Delegating { balance, .. } => *balance,
186+
Voting::Delegating { balance, prior, .. } => *balance.max(&prior.locked()),
187187
}
188188
}
189189

@@ -199,4 +199,11 @@ impl<Balance: Saturating + Ord + Zero + Copy, BlockNumber: Ord + Copy + Zero, Ac
199199
*d = delegations;
200200
*p = prior;
201201
}
202+
203+
pub fn prior(&self) -> &PriorLock<BlockNumber, Balance> {
204+
match self {
205+
Voting::Direct { prior, .. } => prior,
206+
Voting::Delegating { prior, .. } => prior,
207+
}
208+
}
202209
}

0 commit comments

Comments
 (0)