Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Refactors referenda pallet to use fungible traits #1785

Open
wants to merge 13 commits into
base: master
Choose a base branch
from
1 change: 1 addition & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

3 changes: 2 additions & 1 deletion polkadot/runtime/rococo/src/governance/fellowship.rs
Original file line number Diff line number Diff line change
Expand Up @@ -295,11 +295,12 @@ impl pallet_referenda::Config<FellowshipReferendaInstance> for Runtime {
type RuntimeEvent = RuntimeEvent;
type Scheduler = Scheduler;
type Currency = Balances;
type RuntimeHoldReason = RuntimeHoldReason;
type SubmitOrigin =
pallet_ranked_collective::EnsureMember<Runtime, FellowshipCollectiveInstance, 1>;
type CancelOrigin = FellowshipExperts;
type KillOrigin = FellowshipMasters;
type Slash = Treasury;
type OnSlash = pallet_treasury::FunOnUnbalanced<Self, Balances, ()>;
type Votes = pallet_ranked_collective::Votes;
type Tally = pallet_ranked_collective::TallyOf<Runtime, FellowshipCollectiveInstance>;
type SubmissionDeposit = SubmissionDeposit;
Expand Down
3 changes: 2 additions & 1 deletion polkadot/runtime/rococo/src/governance/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -78,10 +78,11 @@ impl pallet_referenda::Config for Runtime {
type RuntimeEvent = RuntimeEvent;
type Scheduler = Scheduler;
type Currency = Balances;
type RuntimeHoldReason = RuntimeHoldReason;
type SubmitOrigin = frame_system::EnsureSigned<AccountId>;
type CancelOrigin = EitherOf<EnsureRoot<AccountId>, ReferendumCanceller>;
type KillOrigin = EitherOf<EnsureRoot<AccountId>, ReferendumKiller>;
type Slash = Treasury;
type OnSlash = pallet_treasury::FunOnUnbalanced<Self, Balances, ()>;
type Votes = pallet_conviction_voting::VotesOf<Runtime>;
type Tally = pallet_conviction_voting::TallyOf<Runtime>;
type SubmissionDeposit = SubmissionDeposit;
Expand Down
4 changes: 2 additions & 2 deletions polkadot/runtime/rococo/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1282,14 +1282,14 @@ construct_runtime! {
// Governance stuff; uncallable initially.
Treasury: pallet_treasury::{Pallet, Call, Storage, Config<T>, Event<T>} = 18,
ConvictionVoting: pallet_conviction_voting::{Pallet, Call, Storage, Event<T>} = 20,
Referenda: pallet_referenda::{Pallet, Call, Storage, Event<T>} = 21,
Referenda: pallet_referenda::{Pallet, Call, Storage, Event<T>, HoldReason} = 21,
// pub type FellowshipCollectiveInstance = pallet_ranked_collective::Instance1;
FellowshipCollective: pallet_ranked_collective::<Instance1>::{
Pallet, Call, Storage, Event<T>
} = 22,
// pub type FellowshipReferendaInstance = pallet_referenda::Instance2;
FellowshipReferenda: pallet_referenda::<Instance2>::{
Pallet, Call, Storage, Event<T>
Pallet, Call, Storage, Event<T>, HoldReason
} = 23,
Origins: pallet_custom_origins::{Origin} = 43,
Whitelist: pallet_whitelist::{Pallet, Call, Storage, Event<T>} = 44,
Expand Down
3 changes: 2 additions & 1 deletion polkadot/runtime/westend/src/governance/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -82,10 +82,11 @@ impl pallet_referenda::Config for Runtime {
type RuntimeEvent = RuntimeEvent;
type Scheduler = Scheduler;
type Currency = Balances;
type RuntimeHoldReason = RuntimeHoldReason;
type SubmitOrigin = frame_system::EnsureSigned<AccountId>;
type CancelOrigin = EitherOf<EnsureRoot<AccountId>, ReferendumCanceller>;
type KillOrigin = EitherOf<EnsureRoot<AccountId>, ReferendumKiller>;
type Slash = Treasury;
type OnSlash = pallet_treasury::FunOnUnbalanced<Self, Balances, ()>;
type Votes = pallet_conviction_voting::VotesOf<Runtime>;
type Tally = pallet_conviction_voting::TallyOf<Runtime>;
type SubmissionDeposit = SubmissionDeposit;
Expand Down
2 changes: 1 addition & 1 deletion polkadot/runtime/westend/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1451,7 +1451,7 @@ construct_runtime! {

// OpenGov
ConvictionVoting: pallet_conviction_voting::{Pallet, Call, Storage, Event<T>} = 31,
Referenda: pallet_referenda::{Pallet, Call, Storage, Event<T>} = 32,
Referenda: pallet_referenda::{Pallet, Call, Storage, Event<T>, HoldReason} = 32,
Origins: pallet_custom_origins::{Origin} = 35,
Whitelist: pallet_whitelist::{Pallet, Call, Storage, Event<T>} = 36,

Expand Down
12 changes: 7 additions & 5 deletions substrate/bin/node/runtime/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -514,7 +514,7 @@ parameter_types! {
impl pallet_balances::Config for Runtime {
type MaxLocks = MaxLocks;
type MaxReserves = MaxReserves;
type ReserveIdentifier = [u8; 8];
type ReserveIdentifier = [u8; 10];
type Balance = Balance;
type DustRemoval = ();
type RuntimeEvent = RuntimeEvent;
Expand Down Expand Up @@ -963,10 +963,11 @@ impl pallet_referenda::Config for Runtime {
type RuntimeEvent = RuntimeEvent;
type Scheduler = Scheduler;
type Currency = pallet_balances::Pallet<Self>;
type RuntimeHoldReason = RuntimeHoldReason;
type SubmitOrigin = EnsureSigned<AccountId>;
type CancelOrigin = EnsureRoot<AccountId>;
type KillOrigin = EnsureRoot<AccountId>;
type Slash = ();
type OnSlash = ();
type Votes = pallet_conviction_voting::VotesOf<Runtime>;
type Tally = pallet_conviction_voting::TallyOf<Runtime>;
type SubmissionDeposit = SubmissionDeposit;
Expand All @@ -983,10 +984,11 @@ impl pallet_referenda::Config<pallet_referenda::Instance2> for Runtime {
type RuntimeEvent = RuntimeEvent;
type Scheduler = Scheduler;
type Currency = pallet_balances::Pallet<Self>;
type RuntimeHoldReason = RuntimeHoldReason;
type SubmitOrigin = EnsureSigned<AccountId>;
type CancelOrigin = EnsureRoot<AccountId>;
type KillOrigin = EnsureRoot<AccountId>;
type Slash = ();
type OnSlash = ();
type Votes = pallet_ranked_collective::Votes;
type Tally = pallet_ranked_collective::TallyOf<Runtime>;
type SubmissionDeposit = SubmissionDeposit;
Expand Down Expand Up @@ -2110,15 +2112,15 @@ construct_runtime!(
VoterList: pallet_bags_list::<Instance1>,
StateTrieMigration: pallet_state_trie_migration,
ChildBounties: pallet_child_bounties,
Referenda: pallet_referenda,
Referenda: pallet_referenda::{Pallet, Call, Storage, Event<T>, HoldReason},
Remark: pallet_remark,
RootTesting: pallet_root_testing,
ConvictionVoting: pallet_conviction_voting,
Whitelist: pallet_whitelist,
AllianceMotion: pallet_collective::<Instance3>,
Alliance: pallet_alliance,
NominationPools: pallet_nomination_pools,
RankedPolls: pallet_referenda::<Instance2>,
RankedPolls: pallet_referenda::<Instance2>::{Pallet, Call, Storage, Event<T>, HoldReason},
RankedCollective: pallet_ranked_collective,
AssetConversion: pallet_asset_conversion,
FastUnstake: pallet_fast_unstake,
Expand Down
1 change: 1 addition & 0 deletions substrate/frame/referenda/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ assert_matches = { version = "1.5" }
pallet-balances = { path = "../balances" }
pallet-preimage = { path = "../preimage" }
pallet-scheduler = { path = "../scheduler" }
pallet-treasury = { path = "../treasury" }
sp-core = { path = "../../primitives/core" }

[features]
Expand Down
68 changes: 52 additions & 16 deletions substrate/frame/referenda/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -69,12 +69,13 @@ use frame_support::{
dispatch::DispatchResult,
ensure,
traits::{
fungible::{hold::Balanced as FnBalanced, MutateHold as FnMutateHold},
schedule::{
v3::{Anon as ScheduleAnon, Named as ScheduleNamed},
DispatchTime,
},
Currency, LockIdentifier, OnUnbalanced, OriginTrait, PollStatus, Polling, QueryPreimage,
ReservableCurrency, StorePreimage, VoteTally,
tokens::{imbalance::OnUnbalanced, Precision},
LockIdentifier, OriginTrait, PollStatus, Polling, QueryPreimage, StorePreimage, VoteTally,
},
BoundedVec,
};
Expand All @@ -95,10 +96,10 @@ use self::branch::{BeginDecidingBranch, OneFewerDecidingBranch, ServiceBranch};
pub use self::{
pallet::*,
types::{
BalanceOf, BoundedCallOf, CallOf, Curve, DecidingStatus, DecidingStatusOf, Deposit,
InsertSorted, NegativeImbalanceOf, PalletsOriginOf, ReferendumIndex, ReferendumInfo,
ReferendumInfoOf, ReferendumStatus, ReferendumStatusOf, ScheduleAddressOf, TallyOf,
TrackIdOf, TrackInfo, TrackInfoOf, TracksInfo, VotesOf,
BalanceOf, BoundedCallOf, CallOf, CreditOf, Curve, DecidingStatus, DecidingStatusOf,
Deposit, InsertSorted, PalletsOriginOf, ReferendumIndex, ReferendumInfo, ReferendumInfoOf,
ReferendumStatus, ReferendumStatusOf, ScheduleAddressOf, TallyOf, TrackIdOf, TrackInfo,
TrackInfoOf, TracksInfo, VotesOf,
},
weights::WeightInfo,
};
Expand Down Expand Up @@ -139,6 +140,7 @@ const ASSEMBLY_ID: LockIdentifier = *b"assembly";

#[frame_support::pallet]
pub mod pallet {

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change

use super::*;
use frame_support::{pallet_prelude::*, traits::EnsureOriginWithArg};
use frame_system::pallet_prelude::*;
Expand All @@ -150,6 +152,13 @@ pub mod pallet {
#[pallet::storage_version(STORAGE_VERSION)]
pub struct Pallet<T, I = ()>(_);

/// A reason for this pallet placing a hold on funds.
#[pallet::composite_enum]
pub enum HoldReason<I: 'static = ()> {
/// The funds are held as deposit to start the referendum's decision phase.
Referendum,
}

#[pallet::config]
pub trait Config<I: 'static = ()>: frame_system::Config + Sized {
// System level stuff.
Expand All @@ -158,10 +167,13 @@ pub mod pallet {
+ From<Call<Self, I>>
+ IsType<<Self as frame_system::Config>::RuntimeCall>
+ From<frame_system::Call<Self>>;

type RuntimeEvent: From<Event<Self, I>>
+ IsType<<Self as frame_system::Config>::RuntimeEvent>;

/// Weight information for extrinsics in this pallet.
type WeightInfo: WeightInfo;

/// The Scheduler.
type Scheduler: ScheduleAnon<
BlockNumberFor<Self>,
Expand All @@ -174,23 +186,34 @@ pub mod pallet {
PalletsOriginOf<Self>,
Hasher = Self::Hashing,
>;

/// Currency type for this pallet.
type Currency: ReservableCurrency<Self::AccountId>;
type Currency: FnMutateHold<Self::AccountId, Reason = Self::RuntimeHoldReason>
+ FnBalanced<Self::AccountId>;

/// The overarching runtime hold reason.
type RuntimeHoldReason: From<HoldReason>;

// Origins and unbalances.
/// Origin from which proposals may be submitted.
type SubmitOrigin: EnsureOriginWithArg<
Self::RuntimeOrigin,
PalletsOriginOf<Self>,
Success = Self::AccountId,
>;

/// Origin from which any vote may be cancelled.
type CancelOrigin: EnsureOrigin<Self::RuntimeOrigin>;

/// Origin from which any vote may be killed.
type KillOrigin: EnsureOrigin<Self::RuntimeOrigin>;

/// Handler for the unbalanced reduction when slashing a preimage deposit.
type Slash: OnUnbalanced<NegativeImbalanceOf<Self, I>>;
type OnSlash: OnUnbalanced<CreditOf<Self, I>>;

/// The counting type for votes. Usually just balance.
type Votes: AtLeast32BitUnsigned + Copy + Parameter + Member + MaxEncodedLen;

/// The tallying type.
type Tally: VoteTally<Self::Votes, TrackIdOf<Self, I>>
+ Clone
Expand Down Expand Up @@ -536,7 +559,7 @@ pub mod pallet {
.take_decision_deposit()
.map_err(|_| Error::<T, I>::Unfinished)?
.ok_or(Error::<T, I>::NoDeposit)?;
Self::refund_deposit(Some(deposit.clone()));
Self::refund_deposit(Some(deposit.clone()))?;
ReferendumInfoFor::<T, I>::insert(index, info);
let e = Event::<T, I>::DecisionDepositRefunded {
index,
Expand Down Expand Up @@ -674,12 +697,12 @@ pub mod pallet {
.take_submission_deposit()
.map_err(|_| Error::<T, I>::BadStatus)?
.ok_or(Error::<T, I>::NoDeposit)?;
Self::refund_deposit(Some(deposit.clone()));
let released = Self::refund_deposit(Some(deposit.clone()))?;
ReferendumInfoFor::<T, I>::insert(index, info);
let e = Event::<T, I>::SubmissionDepositRefunded {
index,
who: deposit.who,
amount: deposit.amount,
amount: released,
};
Self::deposit_event(e);
Ok(())
Expand Down Expand Up @@ -1255,22 +1278,35 @@ impl<T: Config<I>, I: 'static> Pallet<T, I> {
who: T::AccountId,
amount: BalanceOf<T, I>,
) -> Result<Deposit<T::AccountId, BalanceOf<T, I>>, DispatchError> {
T::Currency::reserve(&who, amount)?;
T::Currency::hold(&HoldReason::Referendum.into(), &who, amount)?;
Ok(Deposit { who, amount })
}

/// Return a deposit, if `Some`.
fn refund_deposit(deposit: Option<Deposit<T::AccountId, BalanceOf<T, I>>>) {
fn refund_deposit(
deposit: Option<Deposit<T::AccountId, BalanceOf<T, I>>>,
) -> Result<BalanceOf<T, I>, DispatchError> {
if let Some(Deposit { who, amount }) = deposit {
T::Currency::unreserve(&who, amount);
T::Currency::release(&HoldReason::Referendum.into(), &who, amount, Precision::Exact)
} else {
Ok(Zero::zero())
}
}

/// Slash a deposit, if `Some`.
fn slash_deposit(deposit: Option<Deposit<T::AccountId, BalanceOf<T, I>>>) {
if let Some(Deposit { who, amount }) = deposit {
T::Slash::on_unbalanced(T::Currency::slash_reserved(&who, amount).0);
Self::deposit_event(Event::<T, I>::DepositSlashed { who, amount });
let (imbalance, non_slashed) = <T::Currency as FnBalanced<T::AccountId>>::slash(
&HoldReason::Referendum.into(),
&who,
amount,
);
T::OnSlash::on_unbalanced(imbalance);

Self::deposit_event(Event::<T, I>::DepositSlashed {
who,
amount: amount.saturating_sub(non_slashed),
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think its possible to first emit the event and use imbalance.peek(), that makes it a bit more understandable IMHO.

});
}
}

Expand Down
Loading