Skip to content

Commit

Permalink
Merge pull request #653 from savudani8/feature/referendum-fast-track
Browse files Browse the repository at this point in the history
feat(democracy): fast-track referendum
  • Loading branch information
nud3l committed Jun 27, 2022
2 parents 825030f + e4180a3 commit ee41fef
Show file tree
Hide file tree
Showing 5 changed files with 144 additions and 6 deletions.
4 changes: 3 additions & 1 deletion crates/democracy/README.md
Expand Up @@ -70,10 +70,12 @@ Preimage actions:

#### Fast Track Origin

This call can only be made by the `FastTrackOrigin`.
These calls can only be made by the `FastTrackOrigin`.

- `fast_track` - Schedules the current externally proposed proposal that
is "majority-carries" to become a referendum immediately.
- `fast_track_referendum` - Schedules an active referendum to end in `FastTrackVotingPeriod`
blocks.

#### Root

Expand Down
24 changes: 23 additions & 1 deletion crates/democracy/src/lib.rs
Expand Up @@ -67,6 +67,8 @@
//!
//! - `fast_track` - Schedules the current externally proposed proposal that is "majority-carries" to become a
//! referendum immediately.
//! - `fast_track_referendum` - Schedules an active referendum to end in `FastTrackVotingPeriod`
//! blocks.
//!
//! #### Root
//!
Expand Down Expand Up @@ -327,8 +329,10 @@ pub mod pallet {
Tabled(PropIndex, BalanceOf<T>, Vec<T::AccountId>),
/// A referendum has begun. \[ref_index, threshold\]
Started(ReferendumIndex, VoteThreshold),
/// A referendum has been fast tracked. \[ref_index\]
/// A proposal has been fast tracked. \[ref_index\]
FastTrack(ReferendumIndex),
/// A referendum has been fast tracked. \[ref_index\]
FastTrackReferendum(ReferendumIndex),
/// A proposal has been approved by referendum. \[ref_index\]
Passed(ReferendumIndex),
/// A proposal has been rejected by referendum. \[ref_index\]
Expand Down Expand Up @@ -373,6 +377,9 @@ pub mod pallet {
PreimageMissing,
/// Vote given for invalid referendum
ReferendumInvalid,
/// Fast tracking failed, because the referendum is
/// ending sooner than the fast track voting period.
ReferendumFastTrackFailed,
/// Invalid preimage
PreimageInvalid,
/// No proposals waiting
Expand Down Expand Up @@ -538,6 +545,21 @@ pub mod pallet {
Ok(())
}

#[pallet::weight(T::WeightInfo::fast_track_referendum())]
pub fn fast_track_referendum(origin: OriginFor<T>, #[pallet::compact] ref_index: PropIndex) -> DispatchResult {
T::FastTrackOrigin::ensure_origin(origin)?;
let mut status = Self::referendum_status(ref_index)?;
let now = <frame_system::Pallet<T>>::block_number();
let voting_period = T::FastTrackVotingPeriod::get();
let end_block = now.saturating_add(voting_period);
ensure!(status.end > end_block, Error::<T>::ReferendumFastTrackFailed);
status.end = end_block;

ReferendumInfoOf::<T>::insert(ref_index, ReferendumInfo::Ongoing(status));
Self::deposit_event(Event::<T>::FastTrackReferendum(ref_index));
Ok(())
}

/// Remove a referendum.
///
/// The dispatch origin of this call must be _Root_.
Expand Down
59 changes: 58 additions & 1 deletion crates/democracy/src/tests/fast_tracking.rs
Expand Up @@ -3,7 +3,7 @@
use super::*;

#[test]
fn fast_track_referendum_works() {
fn fast_track_works() {
new_test_ext().execute_with(|| {
System::set_block_number(0);
// let h = set_balance_proposal_hash_and_note(2);
Expand Down Expand Up @@ -32,6 +32,63 @@ fn fast_track_referendum_works() {
});
}

#[test]
fn fast_track_referendum_works() {
new_test_ext().execute_with(|| {
System::set_block_number(0);
let fast_track_voting_period = <tests::Test as Config>::FastTrackVotingPeriod::get();
let ref_index = Democracy::inject_referendum(
fast_track_voting_period * 2,
set_balance_proposal_hash(2),
VoteThreshold::SuperMajorityAgainst,
0,
);

assert_noop!(
Democracy::fast_track_referendum(Origin::signed(1), ref_index),
BadOrigin
);
assert_ok!(Democracy::fast_track_referendum(Origin::signed(5), ref_index));

let start_height = System::block_number();
let end_height = start_height + fast_track_voting_period;
assert_eq!(
Democracy::referendum_status(ref_index),
Ok(ReferendumStatus {
end: end_height,
proposal_hash: set_balance_proposal_hash_and_note(2),
threshold: VoteThreshold::SuperMajorityAgainst,
delay: 0,
tally: Tally {
ayes: 0,
nays: 0,
turnout: 0
},
})
);
});
}

#[test]
fn fast_track_referendum_fails() {
new_test_ext().execute_with(|| {
System::set_block_number(0);
let fast_track_voting_period = <tests::Test as Config>::FastTrackVotingPeriod::get();
let ref_index = Democracy::inject_referendum(
fast_track_voting_period - 1,
set_balance_proposal_hash(2),
VoteThreshold::SuperMajorityAgainst,
0,
);

// Fails because the referendum ends too soon
assert_noop!(
Democracy::fast_track_referendum(Origin::signed(5), ref_index),
Error::<Test>::ReferendumFastTrackFailed
);
});
}

// #[test]
// fn instant_referendum_works() {
// new_test_ext().execute_with(|| {
Expand Down
13 changes: 13 additions & 0 deletions crates/democracy/src/weights.rs
Expand Up @@ -38,6 +38,7 @@ pub trait WeightInfo {
fn external_propose_majority() -> Weight;
fn external_propose_default() -> Weight;
fn fast_track() -> Weight;
fn fast_track_referendum() -> Weight;
fn veto_external(v: u32, ) -> Weight;
fn cancel_proposal(p: u32, ) -> Weight;
fn cancel_referendum() -> Weight;
Expand Down Expand Up @@ -143,6 +144,12 @@ impl<T: frame_system::Config> WeightInfo for SubstrateWeight<T> {
.saturating_add(T::DbWeight::get().reads(2 as Weight))
.saturating_add(T::DbWeight::get().writes(3 as Weight))
}
// Storage: Democracy ReferendumInfoOf (r:1 w:1)
fn fast_track_referendum() -> Weight {
(29_129_000 as Weight)
.saturating_add(T::DbWeight::get().reads(1 as Weight))
.saturating_add(T::DbWeight::get().writes(1 as Weight))
}
// Storage: Democracy NextExternal (r:1 w:1)
// Storage: Democracy Blacklist (r:1 w:1)
fn veto_external(v: u32, ) -> Weight {
Expand Down Expand Up @@ -378,6 +385,12 @@ impl WeightInfo for () {
.saturating_add(RocksDbWeight::get().reads(2 as Weight))
.saturating_add(RocksDbWeight::get().writes(3 as Weight))
}
// Storage: Democracy ReferendumInfoOf (r:1 w:1)
fn fast_track_referendum() -> Weight {
(29_129_000 as Weight)
.saturating_add(RocksDbWeight::get().reads(1 as Weight))
.saturating_add(RocksDbWeight::get().writes(1 as Weight))
}
// Storage: Democracy NextExternal (r:1 w:1)
// Storage: Democracy Blacklist (r:1 w:1)
fn veto_external(v: u32, ) -> Weight {
Expand Down
50 changes: 47 additions & 3 deletions standalone/runtime/tests/test_governance.rs
Expand Up @@ -2,7 +2,7 @@ mod mock;
use crate::assert_eq;
use mock::*;

use democracy::{PropIndex, ReferendumIndex, ReferendumInfo, Vote};
use democracy::{PropIndex, ReferendumIndex, ReferendumInfo, ReferendumStatus, Tally, Vote, VoteThreshold};
use frame_support::traits::{Currency, Hooks};
use orml_vesting::VestingSchedule;
use sp_core::{Encode, Hasher};
Expand Down Expand Up @@ -116,7 +116,7 @@ fn assert_technical_committee_executed_event() {
.expect("execution failed");
}

fn create_proposal(encoded_proposal: Vec<u8>) {
fn create_proposal(encoded_proposal: Vec<u8>) -> H256 {
let proposal_hash = BlakeTwo256::hash(&encoded_proposal[..]);

assert_ok!(
Expand All @@ -128,9 +128,11 @@ fn create_proposal(encoded_proposal: Vec<u8>) {
value: <Runtime as democracy::Config>::MinimumDeposit::get(),
})
.dispatch(origin_of(account_of(ALICE))));

proposal_hash
}

fn create_set_balance_proposal(amount_to_set: Balance) {
fn create_set_balance_proposal(amount_to_set: Balance) -> H256 {
create_proposal(set_balance_proposal(account_of(EVE), amount_to_set))
}

Expand Down Expand Up @@ -395,6 +397,48 @@ fn integration_test_governance_voter_can_change_vote() {
});
}

#[test]
fn integration_test_fast_track_referendum() {
test_with(|| {
let amount_to_set = 1000;
let proposal_hash = create_set_balance_proposal(amount_to_set);

let start_height = <Runtime as democracy::Config>::LaunchPeriod::get();
DemocracyPallet::on_initialize(start_height);
let index = assert_democracy_started_event();

// create motion to fast-track simple-majority referendum
assert_ok!(Call::TechnicalCommittee(TechnicalCommitteeCall::propose {
threshold: 1, // member count
proposal: Box::new(Call::Democracy(DemocracyCall::fast_track_referendum {
ref_index: index,
})),
length_bound: 100000 // length bound
})
.dispatch(origin_of(account_of(ALICE))));
// should be executed immediately with only one member
assert_technical_committee_executed_event();

let now = SystemPallet::block_number();
let fast_track_voting_period = <Runtime as democracy::Config>::FastTrackVotingPeriod::get();
let end = now + fast_track_voting_period;
assert_eq!(
DemocracyPallet::referendum_info(index),
Some(ReferendumInfo::Ongoing(ReferendumStatus {
end,
proposal_hash,
threshold: VoteThreshold::SuperMajorityAgainst,
delay: <Runtime as democracy::Config>::EnactmentPeriod::get(),
tally: Tally {
ayes: 0,
nays: 0,
turnout: 0
},
}))
);
});
}

#[test]
fn integration_test_governance_voter_can_change_vote_with_limited_funds() {
test_with(|| {
Expand Down

0 comments on commit ee41fef

Please sign in to comment.