referrerpolicy=no-referrer-when-downgrade

pallet_democracy/
lib.rs

1// This file is part of Substrate.
2
3// Copyright (C) Parity Technologies (UK) Ltd.
4// SPDX-License-Identifier: Apache-2.0
5
6// Licensed under the Apache License, Version 2.0 (the "License");
7// you may not use this file except in compliance with the License.
8// You may obtain a copy of the License at
9//
10// 	http://www.apache.org/licenses/LICENSE-2.0
11//
12// Unless required by applicable law or agreed to in writing, software
13// distributed under the License is distributed on an "AS IS" BASIS,
14// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15// See the License for the specific language governing permissions and
16// limitations under the License.
17
18//! # Democracy Pallet
19//!
20//! - [`Config`]
21//! - [`Call`]
22//!
23//! ## Overview
24//!
25//! The Democracy pallet handles the administration of general stakeholder voting.
26//!
27//! There are two different queues that a proposal can be added to before it
28//! becomes a referendum, 1) the proposal queue consisting of all public proposals
29//! and 2) the external queue consisting of a single proposal that originates
30//! from one of the _external_ origins (such as a collective group).
31//!
32//! Every launch period - a length defined in the runtime - the Democracy pallet
33//! launches a referendum from a proposal that it takes from either the proposal
34//! queue or the external queue in turn. Any token holder in the system can vote
35//! on referenda. The voting system
36//! uses time-lock voting by allowing the token holder to set their _conviction_
37//! behind a vote. The conviction will dictate the length of time the tokens
38//! will be locked, as well as the multiplier that scales the vote power.
39//!
40//! ### Terminology
41//!
42//! - **Enactment Period:** The minimum period of locking and the period between a proposal being
43//! approved and enacted.
44//! - **Lock Period:** A period of time after proposal enactment that the tokens of _winning_ voters
45//! will be locked.
46//! - **Conviction:** An indication of a voter's strength of belief in their vote. An increase
47//! of one in conviction indicates that a token holder is willing to lock their tokens for twice
48//! as many lock periods after enactment.
49//! - **Vote:** A value that can either be in approval ("Aye") or rejection ("Nay") of a particular
50//!   referendum.
51//! - **Proposal:** A submission to the chain that represents an action that a proposer (either an
52//! account or an external origin) suggests that the system adopt.
53//! - **Referendum:** A proposal that is in the process of being voted on for either acceptance or
54//!   rejection as a change to the system.
55//! - **Delegation:** The act of granting your voting power to the decisions of another account for
56//!   up to a certain conviction.
57//!
58//! ### Adaptive Quorum Biasing
59//!
60//! A _referendum_ can be either simple majority-carries in which 50%+1 of the
61//! votes decide the outcome or _adaptive quorum biased_. Adaptive quorum biasing
62//! makes the threshold for passing or rejecting a referendum higher or lower
63//! depending on how the referendum was originally proposed. There are two types of
64//! adaptive quorum biasing: 1) _positive turnout bias_ makes a referendum
65//! require a super-majority to pass that decreases as turnout increases and
66//! 2) _negative turnout bias_ makes a referendum require a super-majority to
67//! reject that decreases as turnout increases. Another way to think about the
68//! quorum biasing is that _positive bias_ referendums will be rejected by
69//! default and _negative bias_ referendums get passed by default.
70//!
71//! ## Interface
72//!
73//! ### Dispatchable Functions
74//!
75//! #### Public
76//!
77//! These calls can be made from any externally held account capable of creating
78//! a signed extrinsic.
79//!
80//! Basic actions:
81//! - `propose` - Submits a sensitive action, represented as a hash. Requires a deposit.
82//! - `second` - Signals agreement with a proposal, moves it higher on the proposal queue, and
83//!   requires a matching deposit to the original.
84//! - `vote` - Votes in a referendum, either the vote is "Aye" to enact the proposal or "Nay" to
85//!   keep the status quo.
86//! - `unvote` - Cancel a previous vote, this must be done by the voter before the vote ends.
87//! - `delegate` - Delegates the voting power (tokens * conviction) to another account.
88//! - `undelegate` - Stops the delegation of voting power to another account.
89//!
90//! Administration actions that can be done to any account:
91//! - `reap_vote` - Remove some account's expired votes.
92//! - `unlock` - Redetermine the account's balance lock, potentially making tokens available.
93//!
94//! Preimage actions:
95//! - `note_preimage` - Registers the preimage for an upcoming proposal, requires a deposit that is
96//!   returned once the proposal is enacted.
97//! - `note_preimage_operational` - same but provided by `T::OperationalPreimageOrigin`.
98//! - `note_imminent_preimage` - Registers the preimage for an upcoming proposal. Does not require a
99//!   deposit, but the proposal must be in the dispatch queue.
100//! - `note_imminent_preimage_operational` - same but provided by `T::OperationalPreimageOrigin`.
101//! - `reap_preimage` - Removes the preimage for an expired proposal. Will only work under the
102//!   condition that it's the same account that noted it and after the voting period, OR it's a
103//!   different account after the enactment period.
104//!
105//! #### Cancellation Origin
106//!
107//! This call can only be made by the `CancellationOrigin`.
108//!
109//! - `emergency_cancel` - Schedules an emergency cancellation of a referendum. Can only happen once
110//!   to a specific referendum.
111//!
112//! #### ExternalOrigin
113//!
114//! This call can only be made by the `ExternalOrigin`.
115//!
116//! - `external_propose` - Schedules a proposal to become a referendum once it is legal for an
117//!   externally proposed referendum.
118//!
119//! #### External Majority Origin
120//!
121//! This call can only be made by the `ExternalMajorityOrigin`.
122//!
123//! - `external_propose_majority` - Schedules a proposal to become a majority-carries referendum
124//!   once it is legal for an externally proposed referendum.
125//!
126//! #### External Default Origin
127//!
128//! This call can only be made by the `ExternalDefaultOrigin`.
129//!
130//! - `external_propose_default` - Schedules a proposal to become a negative-turnout-bias referendum
131//!   once it is legal for an externally proposed referendum.
132//!
133//! #### Fast Track Origin
134//!
135//! This call can only be made by the `FastTrackOrigin`.
136//!
137//! - `fast_track` - Schedules the current externally proposed proposal that is "majority-carries"
138//!   to become a referendum immediately.
139//!
140//! #### Veto Origin
141//!
142//! This call can only be made by the `VetoOrigin`.
143//!
144//! - `veto_external` - Vetoes and blacklists the external proposal hash.
145//!
146//! #### Root
147//!
148//! - `cancel_referendum` - Removes a referendum.
149//! - `cancel_queued` - Cancels a proposal that is queued for enactment.
150//! - `clear_public_proposal` - Removes all public proposals.
151
152#![recursion_limit = "256"]
153#![cfg_attr(not(feature = "std"), no_std)]
154
155extern crate alloc;
156
157use alloc::{vec, vec::Vec};
158use codec::{Decode, Encode};
159use frame_support::{
160	ensure,
161	traits::{
162		defensive_prelude::*,
163		schedule::{v3::Named as ScheduleNamed, DispatchTime},
164		Bounded, Currency, EnsureOrigin, Get, LockIdentifier, LockableCurrency, OnUnbalanced,
165		QueryPreimage, ReservableCurrency, StorePreimage, WithdrawReasons,
166	},
167	weights::Weight,
168};
169use frame_system::pallet_prelude::{BlockNumberFor, OriginFor};
170use sp_runtime::{
171	traits::{BadOrigin, Bounded as ArithBounded, One, Saturating, StaticLookup, Zero},
172	ArithmeticError, DispatchError, DispatchResult,
173};
174
175mod conviction;
176mod types;
177mod vote;
178mod vote_threshold;
179pub mod weights;
180pub use conviction::Conviction;
181pub use pallet::*;
182pub use types::{
183	Delegations, MetadataOwner, PropIndex, ReferendumIndex, ReferendumInfo, ReferendumStatus,
184	Tally, UnvoteScope,
185};
186pub use vote::{AccountVote, Vote, Voting};
187pub use vote_threshold::{Approved, VoteThreshold};
188pub use weights::WeightInfo;
189
190#[cfg(test)]
191mod tests;
192
193#[cfg(feature = "runtime-benchmarks")]
194pub mod benchmarking;
195
196pub mod migrations;
197
198pub(crate) const DEMOCRACY_ID: LockIdentifier = *b"democrac";
199
200type BalanceOf<T> =
201	<<T as Config>::Currency as Currency<<T as frame_system::Config>::AccountId>>::Balance;
202type NegativeImbalanceOf<T> = <<T as Config>::Currency as Currency<
203	<T as frame_system::Config>::AccountId,
204>>::NegativeImbalance;
205pub type CallOf<T> = <T as frame_system::Config>::RuntimeCall;
206pub type BoundedCallOf<T> = Bounded<CallOf<T>, <T as frame_system::Config>::Hashing>;
207type AccountIdLookupOf<T> = <<T as frame_system::Config>::Lookup as StaticLookup>::Source;
208
209#[frame_support::pallet]
210pub mod pallet {
211	use super::{DispatchResult, *};
212	use frame_support::pallet_prelude::*;
213	use frame_system::pallet_prelude::*;
214
215	/// The in-code storage version.
216	const STORAGE_VERSION: StorageVersion = StorageVersion::new(1);
217
218	#[pallet::pallet]
219	#[pallet::storage_version(STORAGE_VERSION)]
220	pub struct Pallet<T>(_);
221
222	#[pallet::config]
223	pub trait Config: frame_system::Config + Sized {
224		type WeightInfo: WeightInfo;
225		#[allow(deprecated)]
226		type RuntimeEvent: From<Event<Self>> + IsType<<Self as frame_system::Config>::RuntimeEvent>;
227
228		/// The Scheduler.
229		type Scheduler: ScheduleNamed<
230			BlockNumberFor<Self>,
231			CallOf<Self>,
232			Self::PalletsOrigin,
233			Hasher = Self::Hashing,
234		>;
235
236		/// The Preimage provider.
237		type Preimages: QueryPreimage<H = Self::Hashing> + StorePreimage;
238
239		/// Currency type for this pallet.
240		type Currency: ReservableCurrency<Self::AccountId>
241			+ LockableCurrency<Self::AccountId, Moment = BlockNumberFor<Self>>;
242
243		/// The period between a proposal being approved and enacted.
244		///
245		/// It should generally be a little more than the unstake period to ensure that
246		/// voting stakers have an opportunity to remove themselves from the system in the case
247		/// where they are on the losing side of a vote.
248		#[pallet::constant]
249		type EnactmentPeriod: Get<BlockNumberFor<Self>>;
250
251		/// How often (in blocks) new public referenda are launched.
252		#[pallet::constant]
253		type LaunchPeriod: Get<BlockNumberFor<Self>>;
254
255		/// How often (in blocks) to check for new votes.
256		#[pallet::constant]
257		type VotingPeriod: Get<BlockNumberFor<Self>>;
258
259		/// The minimum period of vote locking.
260		///
261		/// It should be no shorter than enactment period to ensure that in the case of an approval,
262		/// those successful voters are locked into the consequences that their votes entail.
263		#[pallet::constant]
264		type VoteLockingPeriod: Get<BlockNumberFor<Self>>;
265
266		/// The minimum amount to be used as a deposit for a public referendum proposal.
267		#[pallet::constant]
268		type MinimumDeposit: Get<BalanceOf<Self>>;
269
270		/// Indicator for whether an emergency origin is even allowed to happen. Some chains may
271		/// want to set this permanently to `false`, others may want to condition it on things such
272		/// as an upgrade having happened recently.
273		#[pallet::constant]
274		type InstantAllowed: Get<bool>;
275
276		/// Minimum voting period allowed for a fast-track referendum.
277		#[pallet::constant]
278		type FastTrackVotingPeriod: Get<BlockNumberFor<Self>>;
279
280		/// Period in blocks where an external proposal may not be re-submitted after being vetoed.
281		#[pallet::constant]
282		type CooloffPeriod: Get<BlockNumberFor<Self>>;
283
284		/// The maximum number of votes for an account.
285		///
286		/// Also used to compute weight, an overly big value can
287		/// lead to extrinsic with very big weight: see `delegate` for instance.
288		#[pallet::constant]
289		type MaxVotes: Get<u32>;
290
291		/// The maximum number of public proposals that can exist at any time.
292		#[pallet::constant]
293		type MaxProposals: Get<u32>;
294
295		/// The maximum number of deposits a public proposal may have at any time.
296		#[pallet::constant]
297		type MaxDeposits: Get<u32>;
298
299		/// The maximum number of items which can be blacklisted.
300		#[pallet::constant]
301		type MaxBlacklisted: Get<u32>;
302
303		/// Origin from which the next tabled referendum may be forced. This is a normal
304		/// "super-majority-required" referendum.
305		type ExternalOrigin: EnsureOrigin<Self::RuntimeOrigin>;
306
307		/// Origin from which the next tabled referendum may be forced; this allows for the tabling
308		/// of a majority-carries referendum.
309		type ExternalMajorityOrigin: EnsureOrigin<Self::RuntimeOrigin>;
310
311		/// Origin from which the next tabled referendum may be forced; this allows for the tabling
312		/// of a negative-turnout-bias (default-carries) referendum.
313		type ExternalDefaultOrigin: EnsureOrigin<Self::RuntimeOrigin>;
314
315		/// Origin from which the new proposal can be made.
316		///
317		/// The success variant is the account id of the depositor.
318		type SubmitOrigin: EnsureOrigin<Self::RuntimeOrigin, Success = Self::AccountId>;
319
320		/// Origin from which the next majority-carries (or more permissive) referendum may be
321		/// tabled to vote according to the `FastTrackVotingPeriod` asynchronously in a similar
322		/// manner to the emergency origin. It retains its threshold method.
323		type FastTrackOrigin: EnsureOrigin<Self::RuntimeOrigin>;
324
325		/// Origin from which the next majority-carries (or more permissive) referendum may be
326		/// tabled to vote immediately and asynchronously in a similar manner to the emergency
327		/// origin. It retains its threshold method.
328		type InstantOrigin: EnsureOrigin<Self::RuntimeOrigin>;
329
330		/// Origin from which any referendum may be cancelled in an emergency.
331		type CancellationOrigin: EnsureOrigin<Self::RuntimeOrigin>;
332
333		/// Origin from which proposals may be blacklisted.
334		type BlacklistOrigin: EnsureOrigin<Self::RuntimeOrigin>;
335
336		/// Origin from which a proposal may be cancelled and its backers slashed.
337		type CancelProposalOrigin: EnsureOrigin<Self::RuntimeOrigin>;
338
339		/// Origin for anyone able to veto proposals.
340		type VetoOrigin: EnsureOrigin<Self::RuntimeOrigin, Success = Self::AccountId>;
341
342		/// Overarching type of all pallets origins.
343		type PalletsOrigin: From<frame_system::RawOrigin<Self::AccountId>>;
344
345		/// Handler for the unbalanced reduction when slashing a preimage deposit.
346		type Slash: OnUnbalanced<NegativeImbalanceOf<Self>>;
347	}
348
349	/// The number of (public) proposals that have been made so far.
350	#[pallet::storage]
351	pub type PublicPropCount<T> = StorageValue<_, PropIndex, ValueQuery>;
352
353	/// The public proposals. Unsorted. The second item is the proposal.
354	#[pallet::storage]
355	pub type PublicProps<T: Config> = StorageValue<
356		_,
357		BoundedVec<(PropIndex, BoundedCallOf<T>, T::AccountId), T::MaxProposals>,
358		ValueQuery,
359	>;
360
361	/// Those who have locked a deposit.
362	///
363	/// TWOX-NOTE: Safe, as increasing integer keys are safe.
364	#[pallet::storage]
365	pub type DepositOf<T: Config> = StorageMap<
366		_,
367		Twox64Concat,
368		PropIndex,
369		(BoundedVec<T::AccountId, T::MaxDeposits>, BalanceOf<T>),
370	>;
371
372	/// The next free referendum index, aka the number of referenda started so far.
373	#[pallet::storage]
374	pub type ReferendumCount<T> = StorageValue<_, ReferendumIndex, ValueQuery>;
375
376	/// The lowest referendum index representing an unbaked referendum. Equal to
377	/// `ReferendumCount` if there isn't a unbaked referendum.
378	#[pallet::storage]
379	pub type LowestUnbaked<T> = StorageValue<_, ReferendumIndex, ValueQuery>;
380
381	/// Information concerning any given referendum.
382	///
383	/// TWOX-NOTE: SAFE as indexes are not under an attacker’s control.
384	#[pallet::storage]
385	pub type ReferendumInfoOf<T: Config> = StorageMap<
386		_,
387		Twox64Concat,
388		ReferendumIndex,
389		ReferendumInfo<BlockNumberFor<T>, BoundedCallOf<T>, BalanceOf<T>>,
390	>;
391
392	/// All votes for a particular voter. We store the balance for the number of votes that we
393	/// have recorded. The second item is the total amount of delegations, that will be added.
394	///
395	/// TWOX-NOTE: SAFE as `AccountId`s are crypto hashes anyway.
396	#[pallet::storage]
397	pub type VotingOf<T: Config> = StorageMap<
398		_,
399		Twox64Concat,
400		T::AccountId,
401		Voting<BalanceOf<T>, T::AccountId, BlockNumberFor<T>, T::MaxVotes>,
402		ValueQuery,
403	>;
404
405	/// True if the last referendum tabled was submitted externally. False if it was a public
406	/// proposal.
407	#[pallet::storage]
408	pub type LastTabledWasExternal<T> = StorageValue<_, bool, ValueQuery>;
409
410	/// The referendum to be tabled whenever it would be valid to table an external proposal.
411	/// This happens when a referendum needs to be tabled and one of two conditions are met:
412	/// - `LastTabledWasExternal` is `false`; or
413	/// - `PublicProps` is empty.
414	#[pallet::storage]
415	pub type NextExternal<T: Config> = StorageValue<_, (BoundedCallOf<T>, VoteThreshold)>;
416
417	/// A record of who vetoed what. Maps proposal hash to a possible existent block number
418	/// (until when it may not be resubmitted) and who vetoed it.
419	#[pallet::storage]
420	pub type Blacklist<T: Config> = StorageMap<
421		_,
422		Identity,
423		T::Hash,
424		(BlockNumberFor<T>, BoundedVec<T::AccountId, T::MaxBlacklisted>),
425	>;
426
427	/// Record of all proposals that have been subject to emergency cancellation.
428	#[pallet::storage]
429	pub type Cancellations<T: Config> = StorageMap<_, Identity, T::Hash, bool, ValueQuery>;
430
431	/// General information concerning any proposal or referendum.
432	/// The `Hash` refers to the preimage of the `Preimages` provider which can be a JSON
433	/// dump or IPFS hash of a JSON file.
434	///
435	/// Consider a garbage collection for a metadata of finished referendums to `unrequest` (remove)
436	/// large preimages.
437	#[pallet::storage]
438	pub type MetadataOf<T: Config> = StorageMap<_, Blake2_128Concat, MetadataOwner, T::Hash>;
439
440	#[pallet::genesis_config]
441	#[derive(frame_support::DefaultNoBound)]
442	pub struct GenesisConfig<T: Config> {
443		#[serde(skip)]
444		_config: core::marker::PhantomData<T>,
445	}
446
447	#[pallet::genesis_build]
448	impl<T: Config> BuildGenesisConfig for GenesisConfig<T> {
449		fn build(&self) {
450			PublicPropCount::<T>::put(0 as PropIndex);
451			ReferendumCount::<T>::put(0 as ReferendumIndex);
452			LowestUnbaked::<T>::put(0 as ReferendumIndex);
453		}
454	}
455
456	#[pallet::event]
457	#[pallet::generate_deposit(pub(super) fn deposit_event)]
458	pub enum Event<T: Config> {
459		/// A motion has been proposed by a public account.
460		Proposed { proposal_index: PropIndex, deposit: BalanceOf<T> },
461		/// A public proposal has been tabled for referendum vote.
462		Tabled { proposal_index: PropIndex, deposit: BalanceOf<T> },
463		/// An external proposal has been tabled.
464		ExternalTabled,
465		/// A referendum has begun.
466		Started { ref_index: ReferendumIndex, threshold: VoteThreshold },
467		/// A proposal has been approved by referendum.
468		Passed { ref_index: ReferendumIndex },
469		/// A proposal has been rejected by referendum.
470		NotPassed { ref_index: ReferendumIndex },
471		/// A referendum has been cancelled.
472		Cancelled { ref_index: ReferendumIndex },
473		/// An account has delegated their vote to another account.
474		Delegated { who: T::AccountId, target: T::AccountId },
475		/// An account has cancelled a previous delegation operation.
476		Undelegated { account: T::AccountId },
477		/// An external proposal has been vetoed.
478		Vetoed { who: T::AccountId, proposal_hash: T::Hash, until: BlockNumberFor<T> },
479		/// A proposal_hash has been blacklisted permanently.
480		Blacklisted { proposal_hash: T::Hash },
481		/// An account has voted in a referendum
482		Voted { voter: T::AccountId, ref_index: ReferendumIndex, vote: AccountVote<BalanceOf<T>> },
483		/// An account has seconded a proposal
484		Seconded { seconder: T::AccountId, prop_index: PropIndex },
485		/// A proposal got canceled.
486		ProposalCanceled { prop_index: PropIndex },
487		/// Metadata for a proposal or a referendum has been set.
488		MetadataSet {
489			/// Metadata owner.
490			owner: MetadataOwner,
491			/// Preimage hash.
492			hash: T::Hash,
493		},
494		/// Metadata for a proposal or a referendum has been cleared.
495		MetadataCleared {
496			/// Metadata owner.
497			owner: MetadataOwner,
498			/// Preimage hash.
499			hash: T::Hash,
500		},
501		/// Metadata has been transferred to new owner.
502		MetadataTransferred {
503			/// Previous metadata owner.
504			prev_owner: MetadataOwner,
505			/// New metadata owner.
506			owner: MetadataOwner,
507			/// Preimage hash.
508			hash: T::Hash,
509		},
510	}
511
512	#[pallet::error]
513	pub enum Error<T> {
514		/// Value too low
515		ValueLow,
516		/// Proposal does not exist
517		ProposalMissing,
518		/// Cannot cancel the same proposal twice
519		AlreadyCanceled,
520		/// Proposal already made
521		DuplicateProposal,
522		/// Proposal still blacklisted
523		ProposalBlacklisted,
524		/// Next external proposal not simple majority
525		NotSimpleMajority,
526		/// Invalid hash
527		InvalidHash,
528		/// No external proposal
529		NoProposal,
530		/// Identity may not veto a proposal twice
531		AlreadyVetoed,
532		/// Vote given for invalid referendum
533		ReferendumInvalid,
534		/// No proposals waiting
535		NoneWaiting,
536		/// The given account did not vote on the referendum.
537		NotVoter,
538		/// The actor has no permission to conduct the action.
539		NoPermission,
540		/// The account is already delegating.
541		AlreadyDelegating,
542		/// Too high a balance was provided that the account cannot afford.
543		InsufficientFunds,
544		/// The account is not currently delegating.
545		NotDelegating,
546		/// The account currently has votes attached to it and the operation cannot succeed until
547		/// these are removed, either through `unvote` or `reap_vote`.
548		VotesExist,
549		/// The instant referendum origin is currently disallowed.
550		InstantNotAllowed,
551		/// Delegation to oneself makes no sense.
552		Nonsense,
553		/// Invalid upper bound.
554		WrongUpperBound,
555		/// Maximum number of votes reached.
556		MaxVotesReached,
557		/// Maximum number of items reached.
558		TooMany,
559		/// Voting period too low
560		VotingPeriodLow,
561		/// The preimage does not exist.
562		PreimageNotExist,
563	}
564
565	#[pallet::hooks]
566	impl<T: Config> Hooks<BlockNumberFor<T>> for Pallet<T> {
567		/// Weight: see `begin_block`
568		fn on_initialize(n: BlockNumberFor<T>) -> Weight {
569			Self::begin_block(n)
570		}
571	}
572
573	#[pallet::call]
574	impl<T: Config> Pallet<T> {
575		/// Propose a sensitive action to be taken.
576		///
577		/// The dispatch origin of this call must be _Signed_ and the sender must
578		/// have funds to cover the deposit.
579		///
580		/// - `proposal_hash`: The hash of the proposal preimage.
581		/// - `value`: The amount of deposit (must be at least `MinimumDeposit`).
582		///
583		/// Emits `Proposed`.
584		#[pallet::call_index(0)]
585		#[pallet::weight(T::WeightInfo::propose())]
586		pub fn propose(
587			origin: OriginFor<T>,
588			proposal: BoundedCallOf<T>,
589			#[pallet::compact] value: BalanceOf<T>,
590		) -> DispatchResult {
591			let who = T::SubmitOrigin::ensure_origin(origin)?;
592			ensure!(value >= T::MinimumDeposit::get(), Error::<T>::ValueLow);
593
594			let index = PublicPropCount::<T>::get();
595			let real_prop_count = PublicProps::<T>::decode_len().unwrap_or(0) as u32;
596			let max_proposals = T::MaxProposals::get();
597			ensure!(real_prop_count < max_proposals, Error::<T>::TooMany);
598			let proposal_hash = proposal.hash();
599
600			if let Some((until, _)) = Blacklist::<T>::get(proposal_hash) {
601				ensure!(
602					frame_system::Pallet::<T>::block_number() >= until,
603					Error::<T>::ProposalBlacklisted,
604				);
605			}
606
607			T::Currency::reserve(&who, value)?;
608
609			let depositors = BoundedVec::<_, T::MaxDeposits>::truncate_from(vec![who.clone()]);
610			DepositOf::<T>::insert(index, (depositors, value));
611
612			PublicPropCount::<T>::put(index + 1);
613
614			PublicProps::<T>::try_append((index, proposal, who))
615				.map_err(|_| Error::<T>::TooMany)?;
616
617			Self::deposit_event(Event::<T>::Proposed { proposal_index: index, deposit: value });
618			Ok(())
619		}
620
621		/// Signals agreement with a particular proposal.
622		///
623		/// The dispatch origin of this call must be _Signed_ and the sender
624		/// must have funds to cover the deposit, equal to the original deposit.
625		///
626		/// - `proposal`: The index of the proposal to second.
627		#[pallet::call_index(1)]
628		#[pallet::weight(T::WeightInfo::second())]
629		pub fn second(
630			origin: OriginFor<T>,
631			#[pallet::compact] proposal: PropIndex,
632		) -> DispatchResult {
633			let who = ensure_signed(origin)?;
634
635			let seconds = Self::len_of_deposit_of(proposal).ok_or(Error::<T>::ProposalMissing)?;
636			ensure!(seconds < T::MaxDeposits::get(), Error::<T>::TooMany);
637			let mut deposit = DepositOf::<T>::get(proposal).ok_or(Error::<T>::ProposalMissing)?;
638			T::Currency::reserve(&who, deposit.1)?;
639			let ok = deposit.0.try_push(who.clone()).is_ok();
640			debug_assert!(ok, "`seconds` is below static limit; `try_insert` should succeed; qed");
641			DepositOf::<T>::insert(proposal, deposit);
642			Self::deposit_event(Event::<T>::Seconded { seconder: who, prop_index: proposal });
643			Ok(())
644		}
645
646		/// Vote in a referendum. If `vote.is_aye()`, the vote is to enact the proposal;
647		/// otherwise it is a vote to keep the status quo.
648		///
649		/// The dispatch origin of this call must be _Signed_.
650		///
651		/// - `ref_index`: The index of the referendum to vote for.
652		/// - `vote`: The vote configuration.
653		#[pallet::call_index(2)]
654		#[pallet::weight(T::WeightInfo::vote_new().max(T::WeightInfo::vote_existing()))]
655		pub fn vote(
656			origin: OriginFor<T>,
657			#[pallet::compact] ref_index: ReferendumIndex,
658			vote: AccountVote<BalanceOf<T>>,
659		) -> DispatchResult {
660			let who = ensure_signed(origin)?;
661			Self::try_vote(&who, ref_index, vote)
662		}
663
664		/// Schedule an emergency cancellation of a referendum. Cannot happen twice to the same
665		/// referendum.
666		///
667		/// The dispatch origin of this call must be `CancellationOrigin`.
668		///
669		/// -`ref_index`: The index of the referendum to cancel.
670		///
671		/// Weight: `O(1)`.
672		#[pallet::call_index(3)]
673		#[pallet::weight((T::WeightInfo::emergency_cancel(), DispatchClass::Operational))]
674		pub fn emergency_cancel(
675			origin: OriginFor<T>,
676			ref_index: ReferendumIndex,
677		) -> DispatchResult {
678			T::CancellationOrigin::ensure_origin(origin)?;
679
680			let status = Self::referendum_status(ref_index)?;
681			let h = status.proposal.hash();
682			ensure!(!Cancellations::<T>::contains_key(h), Error::<T>::AlreadyCanceled);
683
684			Cancellations::<T>::insert(h, true);
685			Self::internal_cancel_referendum(ref_index);
686			Ok(())
687		}
688
689		/// Schedule a referendum to be tabled once it is legal to schedule an external
690		/// referendum.
691		///
692		/// The dispatch origin of this call must be `ExternalOrigin`.
693		///
694		/// - `proposal_hash`: The preimage hash of the proposal.
695		#[pallet::call_index(4)]
696		#[pallet::weight(T::WeightInfo::external_propose())]
697		pub fn external_propose(
698			origin: OriginFor<T>,
699			proposal: BoundedCallOf<T>,
700		) -> DispatchResult {
701			T::ExternalOrigin::ensure_origin(origin)?;
702			ensure!(!NextExternal::<T>::exists(), Error::<T>::DuplicateProposal);
703			if let Some((until, _)) = Blacklist::<T>::get(proposal.hash()) {
704				ensure!(
705					frame_system::Pallet::<T>::block_number() >= until,
706					Error::<T>::ProposalBlacklisted,
707				);
708			}
709			NextExternal::<T>::put((proposal, VoteThreshold::SuperMajorityApprove));
710			Ok(())
711		}
712
713		/// Schedule a majority-carries referendum to be tabled next once it is legal to schedule
714		/// an external referendum.
715		///
716		/// The dispatch of this call must be `ExternalMajorityOrigin`.
717		///
718		/// - `proposal_hash`: The preimage hash of the proposal.
719		///
720		/// Unlike `external_propose`, blacklisting has no effect on this and it may replace a
721		/// pre-scheduled `external_propose` call.
722		///
723		/// Weight: `O(1)`
724		#[pallet::call_index(5)]
725		#[pallet::weight(T::WeightInfo::external_propose_majority())]
726		pub fn external_propose_majority(
727			origin: OriginFor<T>,
728			proposal: BoundedCallOf<T>,
729		) -> DispatchResult {
730			T::ExternalMajorityOrigin::ensure_origin(origin)?;
731			NextExternal::<T>::put((proposal, VoteThreshold::SimpleMajority));
732			Ok(())
733		}
734
735		/// Schedule a negative-turnout-bias referendum to be tabled next once it is legal to
736		/// schedule an external referendum.
737		///
738		/// The dispatch of this call must be `ExternalDefaultOrigin`.
739		///
740		/// - `proposal_hash`: The preimage hash of the proposal.
741		///
742		/// Unlike `external_propose`, blacklisting has no effect on this and it may replace a
743		/// pre-scheduled `external_propose` call.
744		///
745		/// Weight: `O(1)`
746		#[pallet::call_index(6)]
747		#[pallet::weight(T::WeightInfo::external_propose_default())]
748		pub fn external_propose_default(
749			origin: OriginFor<T>,
750			proposal: BoundedCallOf<T>,
751		) -> DispatchResult {
752			T::ExternalDefaultOrigin::ensure_origin(origin)?;
753			NextExternal::<T>::put((proposal, VoteThreshold::SuperMajorityAgainst));
754			Ok(())
755		}
756
757		/// Schedule the currently externally-proposed majority-carries referendum to be tabled
758		/// immediately. If there is no externally-proposed referendum currently, or if there is one
759		/// but it is not a majority-carries referendum then it fails.
760		///
761		/// The dispatch of this call must be `FastTrackOrigin`.
762		///
763		/// - `proposal_hash`: The hash of the current external proposal.
764		/// - `voting_period`: The period that is allowed for voting on this proposal. Increased to
765		/// 	Must be always greater than zero.
766		/// 	For `FastTrackOrigin` must be equal or greater than `FastTrackVotingPeriod`.
767		/// - `delay`: The number of block after voting has ended in approval and this should be
768		///   enacted. This doesn't have a minimum amount.
769		///
770		/// Emits `Started`.
771		///
772		/// Weight: `O(1)`
773		#[pallet::call_index(7)]
774		#[pallet::weight(T::WeightInfo::fast_track())]
775		pub fn fast_track(
776			origin: OriginFor<T>,
777			proposal_hash: T::Hash,
778			voting_period: BlockNumberFor<T>,
779			delay: BlockNumberFor<T>,
780		) -> DispatchResult {
781			// Rather complicated bit of code to ensure that either:
782			// - `voting_period` is at least `FastTrackVotingPeriod` and `origin` is
783			//   `FastTrackOrigin`; or
784			// - `InstantAllowed` is `true` and `origin` is `InstantOrigin`.
785			let maybe_ensure_instant = if voting_period < T::FastTrackVotingPeriod::get() {
786				Some(origin)
787			} else {
788				T::FastTrackOrigin::try_origin(origin).err()
789			};
790			if let Some(ensure_instant) = maybe_ensure_instant {
791				T::InstantOrigin::ensure_origin(ensure_instant)?;
792				ensure!(T::InstantAllowed::get(), Error::<T>::InstantNotAllowed);
793			}
794
795			ensure!(voting_period > Zero::zero(), Error::<T>::VotingPeriodLow);
796			let (ext_proposal, threshold) =
797				NextExternal::<T>::get().ok_or(Error::<T>::ProposalMissing)?;
798			ensure!(
799				threshold != VoteThreshold::SuperMajorityApprove,
800				Error::<T>::NotSimpleMajority,
801			);
802			ensure!(proposal_hash == ext_proposal.hash(), Error::<T>::InvalidHash);
803
804			NextExternal::<T>::kill();
805			let now = frame_system::Pallet::<T>::block_number();
806			let ref_index = Self::inject_referendum(
807				now.saturating_add(voting_period),
808				ext_proposal,
809				threshold,
810				delay,
811			);
812			Self::transfer_metadata(MetadataOwner::External, MetadataOwner::Referendum(ref_index));
813			Ok(())
814		}
815
816		/// Veto and blacklist the external proposal hash.
817		///
818		/// The dispatch origin of this call must be `VetoOrigin`.
819		///
820		/// - `proposal_hash`: The preimage hash of the proposal to veto and blacklist.
821		///
822		/// Emits `Vetoed`.
823		///
824		/// Weight: `O(V + log(V))` where V is number of `existing vetoers`
825		#[pallet::call_index(8)]
826		#[pallet::weight(T::WeightInfo::veto_external())]
827		pub fn veto_external(origin: OriginFor<T>, proposal_hash: T::Hash) -> DispatchResult {
828			let who = T::VetoOrigin::ensure_origin(origin)?;
829
830			if let Some((ext_proposal, _)) = NextExternal::<T>::get() {
831				ensure!(proposal_hash == ext_proposal.hash(), Error::<T>::ProposalMissing);
832			} else {
833				return Err(Error::<T>::NoProposal.into())
834			}
835
836			let mut existing_vetoers =
837				Blacklist::<T>::get(&proposal_hash).map(|pair| pair.1).unwrap_or_default();
838			let insert_position =
839				existing_vetoers.binary_search(&who).err().ok_or(Error::<T>::AlreadyVetoed)?;
840			existing_vetoers
841				.try_insert(insert_position, who.clone())
842				.map_err(|_| Error::<T>::TooMany)?;
843
844			let until =
845				frame_system::Pallet::<T>::block_number().saturating_add(T::CooloffPeriod::get());
846			Blacklist::<T>::insert(&proposal_hash, (until, existing_vetoers));
847
848			Self::deposit_event(Event::<T>::Vetoed { who, proposal_hash, until });
849			NextExternal::<T>::kill();
850			Self::clear_metadata(MetadataOwner::External);
851			Ok(())
852		}
853
854		/// Remove a referendum.
855		///
856		/// The dispatch origin of this call must be _Root_.
857		///
858		/// - `ref_index`: The index of the referendum to cancel.
859		///
860		/// # Weight: `O(1)`.
861		#[pallet::call_index(9)]
862		#[pallet::weight(T::WeightInfo::cancel_referendum())]
863		pub fn cancel_referendum(
864			origin: OriginFor<T>,
865			#[pallet::compact] ref_index: ReferendumIndex,
866		) -> DispatchResult {
867			ensure_root(origin)?;
868			Self::internal_cancel_referendum(ref_index);
869			Ok(())
870		}
871
872		/// Delegate the voting power (with some given conviction) of the sending account.
873		///
874		/// The balance delegated is locked for as long as it's delegated, and thereafter for the
875		/// time appropriate for the conviction's lock period.
876		///
877		/// The dispatch origin of this call must be _Signed_, and the signing account must either:
878		///   - be delegating already; or
879		///   - have no voting activity (if there is, then it will need to be removed/consolidated
880		///     through `reap_vote` or `unvote`).
881		///
882		/// - `to`: The account whose voting the `target` account's voting power will follow.
883		/// - `conviction`: The conviction that will be attached to the delegated votes. When the
884		///   account is undelegated, the funds will be locked for the corresponding period.
885		/// - `balance`: The amount of the account's balance to be used in delegating. This must not
886		///   be more than the account's current balance.
887		///
888		/// Emits `Delegated`.
889		///
890		/// Weight: `O(R)` where R is the number of referendums the voter delegating to has
891		///   voted on. Weight is charged as if maximum votes.
892		// NOTE: weight must cover an incorrect voting of origin with max votes, this is ensure
893		// because a valid delegation cover decoding a direct voting with max votes.
894		#[pallet::call_index(10)]
895		#[pallet::weight(T::WeightInfo::delegate(T::MaxVotes::get()))]
896		pub fn delegate(
897			origin: OriginFor<T>,
898			to: AccountIdLookupOf<T>,
899			conviction: Conviction,
900			balance: BalanceOf<T>,
901		) -> DispatchResultWithPostInfo {
902			let who = ensure_signed(origin)?;
903			let to = T::Lookup::lookup(to)?;
904			let votes = Self::try_delegate(who, to, conviction, balance)?;
905
906			Ok(Some(T::WeightInfo::delegate(votes)).into())
907		}
908
909		/// Undelegate the voting power of the sending account.
910		///
911		/// Tokens may be unlocked following once an amount of time consistent with the lock period
912		/// of the conviction with which the delegation was issued.
913		///
914		/// The dispatch origin of this call must be _Signed_ and the signing account must be
915		/// currently delegating.
916		///
917		/// Emits `Undelegated`.
918		///
919		/// Weight: `O(R)` where R is the number of referendums the voter delegating to has
920		///   voted on. Weight is charged as if maximum votes.
921		// NOTE: weight must cover an incorrect voting of origin with max votes, this is ensure
922		// because a valid delegation cover decoding a direct voting with max votes.
923		#[pallet::call_index(11)]
924		#[pallet::weight(T::WeightInfo::undelegate(T::MaxVotes::get()))]
925		pub fn undelegate(origin: OriginFor<T>) -> DispatchResultWithPostInfo {
926			let who = ensure_signed(origin)?;
927			let votes = Self::try_undelegate(who)?;
928			Ok(Some(T::WeightInfo::undelegate(votes)).into())
929		}
930
931		/// Clears all public proposals.
932		///
933		/// The dispatch origin of this call must be _Root_.
934		///
935		/// Weight: `O(1)`.
936		#[pallet::call_index(12)]
937		#[pallet::weight(T::WeightInfo::clear_public_proposals())]
938		pub fn clear_public_proposals(origin: OriginFor<T>) -> DispatchResult {
939			ensure_root(origin)?;
940			PublicProps::<T>::kill();
941			Ok(())
942		}
943
944		/// Unlock tokens that have an expired lock.
945		///
946		/// The dispatch origin of this call must be _Signed_.
947		///
948		/// - `target`: The account to remove the lock on.
949		///
950		/// Weight: `O(R)` with R number of vote of target.
951		#[pallet::call_index(13)]
952		#[pallet::weight(T::WeightInfo::unlock_set(T::MaxVotes::get()).max(T::WeightInfo::unlock_remove(T::MaxVotes::get())))]
953		pub fn unlock(origin: OriginFor<T>, target: AccountIdLookupOf<T>) -> DispatchResult {
954			ensure_signed(origin)?;
955			let target = T::Lookup::lookup(target)?;
956			Self::update_lock(&target);
957			Ok(())
958		}
959
960		/// Remove a vote for a referendum.
961		///
962		/// If:
963		/// - the referendum was cancelled, or
964		/// - the referendum is ongoing, or
965		/// - the referendum has ended such that
966		///   - the vote of the account was in opposition to the result; or
967		///   - there was no conviction to the account's vote; or
968		///   - the account made a split vote
969		/// ...then the vote is removed cleanly and a following call to `unlock` may result in more
970		/// funds being available.
971		///
972		/// If, however, the referendum has ended and:
973		/// - it finished corresponding to the vote of the account, and
974		/// - the account made a standard vote with conviction, and
975		/// - the lock period of the conviction is not over
976		/// ...then the lock will be aggregated into the overall account's lock, which may involve
977		/// *overlocking* (where the two locks are combined into a single lock that is the maximum
978		/// of both the amount locked and the time is it locked for).
979		///
980		/// The dispatch origin of this call must be _Signed_, and the signer must have a vote
981		/// registered for referendum `index`.
982		///
983		/// - `index`: The index of referendum of the vote to be removed.
984		///
985		/// Weight: `O(R + log R)` where R is the number of referenda that `target` has voted on.
986		///   Weight is calculated for the maximum number of vote.
987		#[pallet::call_index(14)]
988		#[pallet::weight(T::WeightInfo::remove_vote(T::MaxVotes::get()))]
989		pub fn remove_vote(origin: OriginFor<T>, index: ReferendumIndex) -> DispatchResult {
990			let who = ensure_signed(origin)?;
991			Self::try_remove_vote(&who, index, UnvoteScope::Any)
992		}
993
994		/// Remove a vote for a referendum.
995		///
996		/// If the `target` is equal to the signer, then this function is exactly equivalent to
997		/// `remove_vote`. If not equal to the signer, then the vote must have expired,
998		/// either because the referendum was cancelled, because the voter lost the referendum or
999		/// because the conviction period is over.
1000		///
1001		/// The dispatch origin of this call must be _Signed_.
1002		///
1003		/// - `target`: The account of the vote to be removed; this account must have voted for
1004		///   referendum `index`.
1005		/// - `index`: The index of referendum of the vote to be removed.
1006		///
1007		/// Weight: `O(R + log R)` where R is the number of referenda that `target` has voted on.
1008		///   Weight is calculated for the maximum number of vote.
1009		#[pallet::call_index(15)]
1010		#[pallet::weight(T::WeightInfo::remove_other_vote(T::MaxVotes::get()))]
1011		pub fn remove_other_vote(
1012			origin: OriginFor<T>,
1013			target: AccountIdLookupOf<T>,
1014			index: ReferendumIndex,
1015		) -> DispatchResult {
1016			let who = ensure_signed(origin)?;
1017			let target = T::Lookup::lookup(target)?;
1018			let scope = if target == who { UnvoteScope::Any } else { UnvoteScope::OnlyExpired };
1019			Self::try_remove_vote(&target, index, scope)?;
1020			Ok(())
1021		}
1022
1023		/// Permanently place a proposal into the blacklist. This prevents it from ever being
1024		/// proposed again.
1025		///
1026		/// If called on a queued public or external proposal, then this will result in it being
1027		/// removed. If the `ref_index` supplied is an active referendum with the proposal hash,
1028		/// then it will be cancelled.
1029		///
1030		/// The dispatch origin of this call must be `BlacklistOrigin`.
1031		///
1032		/// - `proposal_hash`: The proposal hash to blacklist permanently.
1033		/// - `ref_index`: An ongoing referendum whose hash is `proposal_hash`, which will be
1034		/// cancelled.
1035		///
1036		/// Weight: `O(p)` (though as this is an high-privilege dispatch, we assume it has a
1037		///   reasonable value).
1038		#[pallet::call_index(16)]
1039		#[pallet::weight((T::WeightInfo::blacklist(), DispatchClass::Operational))]
1040		pub fn blacklist(
1041			origin: OriginFor<T>,
1042			proposal_hash: T::Hash,
1043			maybe_ref_index: Option<ReferendumIndex>,
1044		) -> DispatchResult {
1045			T::BlacklistOrigin::ensure_origin(origin)?;
1046
1047			// Insert the proposal into the blacklist.
1048			let permanent =
1049				(BlockNumberFor::<T>::max_value(), BoundedVec::<T::AccountId, _>::default());
1050			Blacklist::<T>::insert(&proposal_hash, permanent);
1051
1052			// Remove the queued proposal, if it's there.
1053			PublicProps::<T>::mutate(|props| {
1054				if let Some(index) = props.iter().position(|p| p.1.hash() == proposal_hash) {
1055					let (prop_index, ..) = props.remove(index);
1056					if let Some((whos, amount)) = DepositOf::<T>::take(prop_index) {
1057						for who in whos.into_iter() {
1058							T::Slash::on_unbalanced(T::Currency::slash_reserved(&who, amount).0);
1059						}
1060					}
1061					Self::clear_metadata(MetadataOwner::Proposal(prop_index));
1062				}
1063			});
1064
1065			// Remove the external queued referendum, if it's there.
1066			if matches!(NextExternal::<T>::get(), Some((p, ..)) if p.hash() == proposal_hash) {
1067				NextExternal::<T>::kill();
1068				Self::clear_metadata(MetadataOwner::External);
1069			}
1070
1071			// Remove the referendum, if it's there.
1072			if let Some(ref_index) = maybe_ref_index {
1073				if let Ok(status) = Self::referendum_status(ref_index) {
1074					if status.proposal.hash() == proposal_hash {
1075						Self::internal_cancel_referendum(ref_index);
1076					}
1077				}
1078			}
1079
1080			Self::deposit_event(Event::<T>::Blacklisted { proposal_hash });
1081			Ok(())
1082		}
1083
1084		/// Remove a proposal.
1085		///
1086		/// The dispatch origin of this call must be `CancelProposalOrigin`.
1087		///
1088		/// - `prop_index`: The index of the proposal to cancel.
1089		///
1090		/// Weight: `O(p)` where `p = PublicProps::<T>::decode_len()`
1091		#[pallet::call_index(17)]
1092		#[pallet::weight(T::WeightInfo::cancel_proposal())]
1093		pub fn cancel_proposal(
1094			origin: OriginFor<T>,
1095			#[pallet::compact] prop_index: PropIndex,
1096		) -> DispatchResult {
1097			T::CancelProposalOrigin::ensure_origin(origin)?;
1098
1099			PublicProps::<T>::mutate(|props| props.retain(|p| p.0 != prop_index));
1100			if let Some((whos, amount)) = DepositOf::<T>::take(prop_index) {
1101				for who in whos.into_iter() {
1102					T::Slash::on_unbalanced(T::Currency::slash_reserved(&who, amount).0);
1103				}
1104			}
1105			Self::deposit_event(Event::<T>::ProposalCanceled { prop_index });
1106			Self::clear_metadata(MetadataOwner::Proposal(prop_index));
1107			Ok(())
1108		}
1109
1110		/// Set or clear a metadata of a proposal or a referendum.
1111		///
1112		/// Parameters:
1113		/// - `origin`: Must correspond to the `MetadataOwner`.
1114		///     - `ExternalOrigin` for an external proposal with the `SuperMajorityApprove`
1115		///       threshold.
1116		///     - `ExternalDefaultOrigin` for an external proposal with the `SuperMajorityAgainst`
1117		///       threshold.
1118		///     - `ExternalMajorityOrigin` for an external proposal with the `SimpleMajority`
1119		///       threshold.
1120		///     - `Signed` by a creator for a public proposal.
1121		///     - `Signed` to clear a metadata for a finished referendum.
1122		///     - `Root` to set a metadata for an ongoing referendum.
1123		/// - `owner`: an identifier of a metadata owner.
1124		/// - `maybe_hash`: The hash of an on-chain stored preimage. `None` to clear a metadata.
1125		#[pallet::call_index(18)]
1126		#[pallet::weight(
1127			match (owner, maybe_hash) {
1128				(MetadataOwner::External, Some(_)) => T::WeightInfo::set_external_metadata(),
1129				(MetadataOwner::External, None) => T::WeightInfo::clear_external_metadata(),
1130				(MetadataOwner::Proposal(_), Some(_)) => T::WeightInfo::set_proposal_metadata(),
1131				(MetadataOwner::Proposal(_), None) => T::WeightInfo::clear_proposal_metadata(),
1132				(MetadataOwner::Referendum(_), Some(_)) => T::WeightInfo::set_referendum_metadata(),
1133				(MetadataOwner::Referendum(_), None) => T::WeightInfo::clear_referendum_metadata(),
1134			}
1135		)]
1136		pub fn set_metadata(
1137			origin: OriginFor<T>,
1138			owner: MetadataOwner,
1139			maybe_hash: Option<T::Hash>,
1140		) -> DispatchResult {
1141			match owner {
1142				MetadataOwner::External => {
1143					let (_, threshold) = NextExternal::<T>::get().ok_or(Error::<T>::NoProposal)?;
1144					Self::ensure_external_origin(threshold, origin)?;
1145				},
1146				MetadataOwner::Proposal(index) => {
1147					let who = ensure_signed(origin)?;
1148					let (_, _, proposer) = Self::proposal(index)?;
1149					ensure!(proposer == who, Error::<T>::NoPermission);
1150				},
1151				MetadataOwner::Referendum(index) => {
1152					let is_root = ensure_signed_or_root(origin)?.is_none();
1153					ensure!(is_root || maybe_hash.is_none(), Error::<T>::NoPermission);
1154					ensure!(
1155						is_root || Self::referendum_status(index).is_err(),
1156						Error::<T>::NoPermission
1157					);
1158				},
1159			}
1160			if let Some(hash) = maybe_hash {
1161				ensure!(T::Preimages::len(&hash).is_some(), Error::<T>::PreimageNotExist);
1162				MetadataOf::<T>::insert(owner.clone(), hash);
1163				Self::deposit_event(Event::<T>::MetadataSet { owner, hash });
1164			} else {
1165				Self::clear_metadata(owner);
1166			}
1167			Ok(())
1168		}
1169	}
1170}
1171
1172pub trait EncodeInto: Encode {
1173	fn encode_into<T: AsMut<[u8]> + Default, H: sp_core::Hasher>(&self) -> T {
1174		let mut t = T::default();
1175		self.using_encoded(|data| {
1176			if data.len() <= t.as_mut().len() {
1177				t.as_mut()[0..data.len()].copy_from_slice(data);
1178			} else {
1179				// encoded self is too big to fit into a T.
1180				// hash it and use the first bytes of that instead.
1181				let hash = H::hash(&data);
1182				let hash = hash.as_ref();
1183				let l = t.as_mut().len().min(hash.len());
1184				t.as_mut()[0..l].copy_from_slice(&hash[0..l]);
1185			}
1186		});
1187		t
1188	}
1189}
1190impl<T: Encode> EncodeInto for T {}
1191
1192impl<T: Config> Pallet<T> {
1193	// exposed immutables.
1194
1195	/// Get the amount locked in support of `proposal`; `None` if proposal isn't a valid proposal
1196	/// index.
1197	pub fn backing_for(proposal: PropIndex) -> Option<BalanceOf<T>> {
1198		DepositOf::<T>::get(proposal).map(|(l, d)| d.saturating_mul((l.len() as u32).into()))
1199	}
1200
1201	/// Get all referenda ready for tally at block `n`.
1202	pub fn maturing_referenda_at(
1203		n: BlockNumberFor<T>,
1204	) -> Vec<(ReferendumIndex, ReferendumStatus<BlockNumberFor<T>, BoundedCallOf<T>, BalanceOf<T>>)>
1205	{
1206		let next = LowestUnbaked::<T>::get();
1207		let last = ReferendumCount::<T>::get();
1208		Self::maturing_referenda_at_inner(n, next..last)
1209	}
1210
1211	fn maturing_referenda_at_inner(
1212		n: BlockNumberFor<T>,
1213		range: core::ops::Range<PropIndex>,
1214	) -> Vec<(ReferendumIndex, ReferendumStatus<BlockNumberFor<T>, BoundedCallOf<T>, BalanceOf<T>>)>
1215	{
1216		range
1217			.into_iter()
1218			.map(|i| (i, ReferendumInfoOf::<T>::get(i)))
1219			.filter_map(|(i, maybe_info)| match maybe_info {
1220				Some(ReferendumInfo::Ongoing(status)) => Some((i, status)),
1221				_ => None,
1222			})
1223			.filter(|(_, status)| status.end == n)
1224			.collect()
1225	}
1226
1227	// Exposed mutables.
1228
1229	/// Start a referendum.
1230	pub fn internal_start_referendum(
1231		proposal: BoundedCallOf<T>,
1232		threshold: VoteThreshold,
1233		delay: BlockNumberFor<T>,
1234	) -> ReferendumIndex {
1235		Pallet::<T>::inject_referendum(
1236			frame_system::Pallet::<T>::block_number().saturating_add(T::VotingPeriod::get()),
1237			proposal,
1238			threshold,
1239			delay,
1240		)
1241	}
1242
1243	/// Remove a referendum.
1244	pub fn internal_cancel_referendum(ref_index: ReferendumIndex) {
1245		Self::deposit_event(Event::<T>::Cancelled { ref_index });
1246		ReferendumInfoOf::<T>::remove(ref_index);
1247		Self::clear_metadata(MetadataOwner::Referendum(ref_index));
1248	}
1249
1250	// private.
1251
1252	/// Ok if the given referendum is active, Err otherwise
1253	fn ensure_ongoing(
1254		r: ReferendumInfo<BlockNumberFor<T>, BoundedCallOf<T>, BalanceOf<T>>,
1255	) -> Result<ReferendumStatus<BlockNumberFor<T>, BoundedCallOf<T>, BalanceOf<T>>, DispatchError>
1256	{
1257		match r {
1258			ReferendumInfo::Ongoing(s) => Ok(s),
1259			_ => Err(Error::<T>::ReferendumInvalid.into()),
1260		}
1261	}
1262
1263	fn referendum_status(
1264		ref_index: ReferendumIndex,
1265	) -> Result<ReferendumStatus<BlockNumberFor<T>, BoundedCallOf<T>, BalanceOf<T>>, DispatchError>
1266	{
1267		let info = ReferendumInfoOf::<T>::get(ref_index).ok_or(Error::<T>::ReferendumInvalid)?;
1268		Self::ensure_ongoing(info)
1269	}
1270
1271	/// Actually enact a vote, if legit.
1272	fn try_vote(
1273		who: &T::AccountId,
1274		ref_index: ReferendumIndex,
1275		vote: AccountVote<BalanceOf<T>>,
1276	) -> DispatchResult {
1277		let mut status = Self::referendum_status(ref_index)?;
1278		ensure!(vote.balance() <= T::Currency::free_balance(who), Error::<T>::InsufficientFunds);
1279		VotingOf::<T>::try_mutate(who, |voting| -> DispatchResult {
1280			if let Voting::Direct { ref mut votes, delegations, .. } = voting {
1281				match votes.binary_search_by_key(&ref_index, |i| i.0) {
1282					Ok(i) => {
1283						// Shouldn't be possible to fail, but we handle it gracefully.
1284						status.tally.remove(votes[i].1).ok_or(ArithmeticError::Underflow)?;
1285						if let Some(approve) = votes[i].1.as_standard() {
1286							status.tally.reduce(approve, *delegations);
1287						}
1288						votes[i].1 = vote;
1289					},
1290					Err(i) => {
1291						votes
1292							.try_insert(i, (ref_index, vote))
1293							.map_err(|_| Error::<T>::MaxVotesReached)?;
1294					},
1295				}
1296				Self::deposit_event(Event::<T>::Voted { voter: who.clone(), ref_index, vote });
1297				// Shouldn't be possible to fail, but we handle it gracefully.
1298				status.tally.add(vote).ok_or(ArithmeticError::Overflow)?;
1299				if let Some(approve) = vote.as_standard() {
1300					status.tally.increase(approve, *delegations);
1301				}
1302				Ok(())
1303			} else {
1304				Err(Error::<T>::AlreadyDelegating.into())
1305			}
1306		})?;
1307		// Extend the lock to `balance` (rather than setting it) since we don't know what other
1308		// votes are in place.
1309		T::Currency::extend_lock(
1310			DEMOCRACY_ID,
1311			who,
1312			vote.balance(),
1313			WithdrawReasons::except(WithdrawReasons::RESERVE),
1314		);
1315		ReferendumInfoOf::<T>::insert(ref_index, ReferendumInfo::Ongoing(status));
1316		Ok(())
1317	}
1318
1319	/// Remove the account's vote for the given referendum if possible. This is possible when:
1320	/// - The referendum has not finished.
1321	/// - The referendum has finished and the voter lost their direction.
1322	/// - The referendum has finished and the voter's lock period is up.
1323	///
1324	/// This will generally be combined with a call to `unlock`.
1325	fn try_remove_vote(
1326		who: &T::AccountId,
1327		ref_index: ReferendumIndex,
1328		scope: UnvoteScope,
1329	) -> DispatchResult {
1330		let info = ReferendumInfoOf::<T>::get(ref_index);
1331		VotingOf::<T>::try_mutate(who, |voting| -> DispatchResult {
1332			if let Voting::Direct { ref mut votes, delegations, ref mut prior } = voting {
1333				let i = votes
1334					.binary_search_by_key(&ref_index, |i| i.0)
1335					.map_err(|_| Error::<T>::NotVoter)?;
1336				match info {
1337					Some(ReferendumInfo::Ongoing(mut status)) => {
1338						ensure!(matches!(scope, UnvoteScope::Any), Error::<T>::NoPermission);
1339						// Shouldn't be possible to fail, but we handle it gracefully.
1340						status.tally.remove(votes[i].1).ok_or(ArithmeticError::Underflow)?;
1341						if let Some(approve) = votes[i].1.as_standard() {
1342							status.tally.reduce(approve, *delegations);
1343						}
1344						ReferendumInfoOf::<T>::insert(ref_index, ReferendumInfo::Ongoing(status));
1345					},
1346					Some(ReferendumInfo::Finished { end, approved }) => {
1347						if let Some((lock_periods, balance)) = votes[i].1.locked_if(approved) {
1348							let unlock_at = end.saturating_add(
1349								T::VoteLockingPeriod::get().saturating_mul(lock_periods.into()),
1350							);
1351							let now = frame_system::Pallet::<T>::block_number();
1352							if now < unlock_at {
1353								ensure!(
1354									matches!(scope, UnvoteScope::Any),
1355									Error::<T>::NoPermission
1356								);
1357								prior.accumulate(unlock_at, balance)
1358							}
1359						}
1360					},
1361					None => {}, // Referendum was cancelled.
1362				}
1363				votes.remove(i);
1364			}
1365			Ok(())
1366		})?;
1367		Ok(())
1368	}
1369
1370	/// Return the number of votes for `who`
1371	fn increase_upstream_delegation(who: &T::AccountId, amount: Delegations<BalanceOf<T>>) -> u32 {
1372		VotingOf::<T>::mutate(who, |voting| match voting {
1373			Voting::Delegating { delegations, .. } => {
1374				// We don't support second level delegating, so we don't need to do anything more.
1375				*delegations = delegations.saturating_add(amount);
1376				1
1377			},
1378			Voting::Direct { votes, delegations, .. } => {
1379				*delegations = delegations.saturating_add(amount);
1380				for &(ref_index, account_vote) in votes.iter() {
1381					if let AccountVote::Standard { vote, .. } = account_vote {
1382						ReferendumInfoOf::<T>::mutate(ref_index, |maybe_info| {
1383							if let Some(ReferendumInfo::Ongoing(ref mut status)) = maybe_info {
1384								status.tally.increase(vote.aye, amount);
1385							}
1386						});
1387					}
1388				}
1389				votes.len() as u32
1390			},
1391		})
1392	}
1393
1394	/// Return the number of votes for `who`
1395	fn reduce_upstream_delegation(who: &T::AccountId, amount: Delegations<BalanceOf<T>>) -> u32 {
1396		VotingOf::<T>::mutate(who, |voting| match voting {
1397			Voting::Delegating { delegations, .. } => {
1398				// We don't support second level delegating, so we don't need to do anything more.
1399				*delegations = delegations.saturating_sub(amount);
1400				1
1401			},
1402			Voting::Direct { votes, delegations, .. } => {
1403				*delegations = delegations.saturating_sub(amount);
1404				for &(ref_index, account_vote) in votes.iter() {
1405					if let AccountVote::Standard { vote, .. } = account_vote {
1406						ReferendumInfoOf::<T>::mutate(ref_index, |maybe_info| {
1407							if let Some(ReferendumInfo::Ongoing(ref mut status)) = maybe_info {
1408								status.tally.reduce(vote.aye, amount);
1409							}
1410						});
1411					}
1412				}
1413				votes.len() as u32
1414			},
1415		})
1416	}
1417
1418	/// Attempt to delegate `balance` times `conviction` of voting power from `who` to `target`.
1419	///
1420	/// Return the upstream number of votes.
1421	fn try_delegate(
1422		who: T::AccountId,
1423		target: T::AccountId,
1424		conviction: Conviction,
1425		balance: BalanceOf<T>,
1426	) -> Result<u32, DispatchError> {
1427		ensure!(who != target, Error::<T>::Nonsense);
1428		ensure!(balance <= T::Currency::free_balance(&who), Error::<T>::InsufficientFunds);
1429		let votes = VotingOf::<T>::try_mutate(&who, |voting| -> Result<u32, DispatchError> {
1430			let mut old = Voting::Delegating {
1431				balance,
1432				target: target.clone(),
1433				conviction,
1434				delegations: Default::default(),
1435				prior: Default::default(),
1436			};
1437			core::mem::swap(&mut old, voting);
1438			match old {
1439				Voting::Delegating {
1440					balance, target, conviction, delegations, mut prior, ..
1441				} => {
1442					// remove any delegation votes to our current target.
1443					Self::reduce_upstream_delegation(&target, conviction.votes(balance));
1444					let now = frame_system::Pallet::<T>::block_number();
1445					let lock_periods = conviction.lock_periods().into();
1446					let unlock_block = now
1447						.saturating_add(T::VoteLockingPeriod::get().saturating_mul(lock_periods));
1448					prior.accumulate(unlock_block, balance);
1449					voting.set_common(delegations, prior);
1450				},
1451				Voting::Direct { votes, delegations, prior } => {
1452					// here we just ensure that we're currently idling with no votes recorded.
1453					ensure!(votes.is_empty(), Error::<T>::VotesExist);
1454					voting.set_common(delegations, prior);
1455				},
1456			}
1457			let votes = Self::increase_upstream_delegation(&target, conviction.votes(balance));
1458			// Extend the lock to `balance` (rather than setting it) since we don't know what other
1459			// votes are in place.
1460			T::Currency::extend_lock(
1461				DEMOCRACY_ID,
1462				&who,
1463				balance,
1464				WithdrawReasons::except(WithdrawReasons::RESERVE),
1465			);
1466			Ok(votes)
1467		})?;
1468		Self::deposit_event(Event::<T>::Delegated { who, target });
1469		Ok(votes)
1470	}
1471
1472	/// Attempt to end the current delegation.
1473	///
1474	/// Return the number of votes of upstream.
1475	fn try_undelegate(who: T::AccountId) -> Result<u32, DispatchError> {
1476		let votes = VotingOf::<T>::try_mutate(&who, |voting| -> Result<u32, DispatchError> {
1477			let mut old = Voting::default();
1478			core::mem::swap(&mut old, voting);
1479			match old {
1480				Voting::Delegating { balance, target, conviction, delegations, mut prior } => {
1481					// remove any delegation votes to our current target.
1482					let votes =
1483						Self::reduce_upstream_delegation(&target, conviction.votes(balance));
1484					let now = frame_system::Pallet::<T>::block_number();
1485					let lock_periods = conviction.lock_periods().into();
1486					let unlock_block = now
1487						.saturating_add(T::VoteLockingPeriod::get().saturating_mul(lock_periods));
1488					prior.accumulate(unlock_block, balance);
1489					voting.set_common(delegations, prior);
1490
1491					Ok(votes)
1492				},
1493				Voting::Direct { .. } => Err(Error::<T>::NotDelegating.into()),
1494			}
1495		})?;
1496		Self::deposit_event(Event::<T>::Undelegated { account: who });
1497		Ok(votes)
1498	}
1499
1500	/// Rejig the lock on an account. It will never get more stringent (since that would indicate
1501	/// a security hole) but may be reduced from what they are currently.
1502	fn update_lock(who: &T::AccountId) {
1503		let lock_needed = VotingOf::<T>::mutate(who, |voting| {
1504			voting.rejig(frame_system::Pallet::<T>::block_number());
1505			voting.locked_balance()
1506		});
1507		if lock_needed.is_zero() {
1508			T::Currency::remove_lock(DEMOCRACY_ID, who);
1509		} else {
1510			T::Currency::set_lock(
1511				DEMOCRACY_ID,
1512				who,
1513				lock_needed,
1514				WithdrawReasons::except(WithdrawReasons::RESERVE),
1515			);
1516		}
1517	}
1518
1519	/// Start a referendum
1520	fn inject_referendum(
1521		end: BlockNumberFor<T>,
1522		proposal: BoundedCallOf<T>,
1523		threshold: VoteThreshold,
1524		delay: BlockNumberFor<T>,
1525	) -> ReferendumIndex {
1526		let ref_index = ReferendumCount::<T>::get();
1527		ReferendumCount::<T>::put(ref_index + 1);
1528		let status =
1529			ReferendumStatus { end, proposal, threshold, delay, tally: Default::default() };
1530		let item = ReferendumInfo::Ongoing(status);
1531		ReferendumInfoOf::<T>::insert(ref_index, item);
1532		Self::deposit_event(Event::<T>::Started { ref_index, threshold });
1533		ref_index
1534	}
1535
1536	/// Table the next waiting proposal for a vote.
1537	fn launch_next(now: BlockNumberFor<T>) -> DispatchResult {
1538		if LastTabledWasExternal::<T>::take() {
1539			Self::launch_public(now).or_else(|_| Self::launch_external(now))
1540		} else {
1541			Self::launch_external(now).or_else(|_| Self::launch_public(now))
1542		}
1543		.map_err(|_| Error::<T>::NoneWaiting.into())
1544	}
1545
1546	/// Table the waiting external proposal for a vote, if there is one.
1547	fn launch_external(now: BlockNumberFor<T>) -> DispatchResult {
1548		if let Some((proposal, threshold)) = NextExternal::<T>::take() {
1549			LastTabledWasExternal::<T>::put(true);
1550			Self::deposit_event(Event::<T>::ExternalTabled);
1551			let ref_index = Self::inject_referendum(
1552				now.saturating_add(T::VotingPeriod::get()),
1553				proposal,
1554				threshold,
1555				T::EnactmentPeriod::get(),
1556			);
1557			Self::transfer_metadata(MetadataOwner::External, MetadataOwner::Referendum(ref_index));
1558			Ok(())
1559		} else {
1560			return Err(Error::<T>::NoneWaiting.into())
1561		}
1562	}
1563
1564	/// Table the waiting public proposal with the highest backing for a vote.
1565	fn launch_public(now: BlockNumberFor<T>) -> DispatchResult {
1566		let mut public_props = PublicProps::<T>::get();
1567		if let Some((winner_index, _)) = public_props.iter().enumerate().max_by_key(
1568			// defensive only: All current public proposals have an amount locked
1569			|x| Self::backing_for((x.1).0).defensive_unwrap_or_else(Zero::zero),
1570		) {
1571			let (prop_index, proposal, _) = public_props.swap_remove(winner_index);
1572			PublicProps::<T>::put(public_props);
1573
1574			if let Some((depositors, deposit)) = DepositOf::<T>::take(prop_index) {
1575				// refund depositors
1576				for d in depositors.iter() {
1577					T::Currency::unreserve(d, deposit);
1578				}
1579				Self::deposit_event(Event::<T>::Tabled { proposal_index: prop_index, deposit });
1580				let ref_index = Self::inject_referendum(
1581					now.saturating_add(T::VotingPeriod::get()),
1582					proposal,
1583					VoteThreshold::SuperMajorityApprove,
1584					T::EnactmentPeriod::get(),
1585				);
1586				Self::transfer_metadata(
1587					MetadataOwner::Proposal(prop_index),
1588					MetadataOwner::Referendum(ref_index),
1589				)
1590			}
1591			Ok(())
1592		} else {
1593			return Err(Error::<T>::NoneWaiting.into())
1594		}
1595	}
1596
1597	fn bake_referendum(
1598		now: BlockNumberFor<T>,
1599		index: ReferendumIndex,
1600		status: ReferendumStatus<BlockNumberFor<T>, BoundedCallOf<T>, BalanceOf<T>>,
1601	) -> bool {
1602		let total_issuance = T::Currency::total_issuance();
1603		let approved = status.threshold.approved(status.tally, total_issuance);
1604
1605		if approved {
1606			Self::deposit_event(Event::<T>::Passed { ref_index: index });
1607
1608			// Earliest it can be scheduled for is next block.
1609			let when = now.saturating_add(status.delay.max(One::one()));
1610			if T::Scheduler::schedule_named(
1611				(DEMOCRACY_ID, index).encode_into::<_, T::Hashing>(),
1612				DispatchTime::At(when),
1613				None,
1614				63,
1615				frame_system::RawOrigin::Root.into(),
1616				status.proposal,
1617			)
1618			.is_err()
1619			{
1620				frame_support::print("LOGIC ERROR: bake_referendum/schedule_named failed");
1621			}
1622		} else {
1623			Self::deposit_event(Event::<T>::NotPassed { ref_index: index });
1624		}
1625
1626		approved
1627	}
1628
1629	/// Current era is ending; we should finish up any proposals.
1630	///
1631	///
1632	/// ## Complexity:
1633	/// If a referendum is launched or maturing, this will take full block weight if queue is not
1634	/// empty. Otherwise, `O(R)` where `R` is the number of unbaked referenda.
1635	fn begin_block(now: BlockNumberFor<T>) -> Weight {
1636		let max_block_weight = T::BlockWeights::get().max_block;
1637		let mut weight = Weight::zero();
1638
1639		let next = LowestUnbaked::<T>::get();
1640		let last = ReferendumCount::<T>::get();
1641		let r = last.saturating_sub(next);
1642
1643		// pick out another public referendum if it's time.
1644		if (now % T::LaunchPeriod::get()).is_zero() {
1645			// Errors come from the queue being empty. If the queue is not empty, it will take
1646			// full block weight.
1647			if Self::launch_next(now).is_ok() {
1648				weight = max_block_weight;
1649			} else {
1650				weight.saturating_accrue(T::WeightInfo::on_initialize_base_with_launch_period(r));
1651			}
1652		} else {
1653			weight.saturating_accrue(T::WeightInfo::on_initialize_base(r));
1654		}
1655
1656		// tally up votes for any expiring referenda.
1657		for (index, info) in Self::maturing_referenda_at_inner(now, next..last).into_iter() {
1658			let approved = Self::bake_referendum(now, index, info);
1659			ReferendumInfoOf::<T>::insert(index, ReferendumInfo::Finished { end: now, approved });
1660			weight = max_block_weight;
1661		}
1662
1663		// Notes:
1664		// * We don't consider the lowest unbaked to be the last maturing in case some referenda
1665		//   have a longer voting period than others.
1666		// * The iteration here shouldn't trigger any storage read that are not in cache, due to
1667		//   `maturing_referenda_at_inner` having already read them.
1668		// * We shouldn't iterate more than `LaunchPeriod/VotingPeriod + 1` times because the number
1669		//   of unbaked referendum is bounded by this number. In case those number have changed in a
1670		//   runtime upgrade the formula should be adjusted but the bound should still be sensible.
1671		LowestUnbaked::<T>::mutate(|ref_index| {
1672			while *ref_index < last &&
1673				ReferendumInfoOf::<T>::get(*ref_index)
1674					.map_or(true, |info| matches!(info, ReferendumInfo::Finished { .. }))
1675			{
1676				*ref_index += 1
1677			}
1678		});
1679
1680		weight
1681	}
1682
1683	/// Reads the length of account in DepositOf without getting the complete value in the runtime.
1684	///
1685	/// Return 0 if no deposit for this proposal.
1686	fn len_of_deposit_of(proposal: PropIndex) -> Option<u32> {
1687		// DepositOf first tuple element is a vec, decoding its len is equivalent to decode a
1688		// `Compact<u32>`.
1689		decode_compact_u32_at(&DepositOf::<T>::hashed_key_for(proposal))
1690	}
1691
1692	/// Return a proposal of an index.
1693	fn proposal(index: PropIndex) -> Result<(PropIndex, BoundedCallOf<T>, T::AccountId), Error<T>> {
1694		PublicProps::<T>::get()
1695			.into_iter()
1696			.find(|(prop_index, _, _)| prop_index == &index)
1697			.ok_or(Error::<T>::ProposalMissing)
1698	}
1699
1700	/// Clear metadata if exist for a given owner.
1701	fn clear_metadata(owner: MetadataOwner) {
1702		if let Some(hash) = MetadataOf::<T>::take(&owner) {
1703			Self::deposit_event(Event::<T>::MetadataCleared { owner, hash });
1704		}
1705	}
1706
1707	/// Transfer the metadata of an `owner` to a `new_owner`.
1708	fn transfer_metadata(owner: MetadataOwner, new_owner: MetadataOwner) {
1709		if let Some(hash) = MetadataOf::<T>::take(&owner) {
1710			MetadataOf::<T>::insert(&new_owner, hash);
1711			Self::deposit_event(Event::<T>::MetadataTransferred {
1712				prev_owner: owner,
1713				owner: new_owner,
1714				hash,
1715			});
1716		}
1717	}
1718
1719	/// Ensure external origin for corresponding vote threshold.
1720	fn ensure_external_origin(
1721		threshold: VoteThreshold,
1722		origin: OriginFor<T>,
1723	) -> Result<(), BadOrigin> {
1724		match threshold {
1725			VoteThreshold::SuperMajorityApprove => {
1726				T::ExternalOrigin::ensure_origin(origin)?;
1727			},
1728			VoteThreshold::SuperMajorityAgainst => {
1729				T::ExternalDefaultOrigin::ensure_origin(origin)?;
1730			},
1731			VoteThreshold::SimpleMajority => {
1732				T::ExternalMajorityOrigin::ensure_origin(origin)?;
1733			},
1734		};
1735		Ok(())
1736	}
1737}
1738
1739/// Decode `Compact<u32>` from the trie at given key.
1740fn decode_compact_u32_at(key: &[u8]) -> Option<u32> {
1741	// `Compact<u32>` takes at most 5 bytes.
1742	let mut buf = [0u8; 5];
1743	let bytes = sp_io::storage::read(key, &mut buf, 0)?;
1744	// The value may be smaller than 5 bytes.
1745	let mut input = &buf[0..buf.len().min(bytes as usize)];
1746	match codec::Compact::<u32>::decode(&mut input) {
1747		Ok(c) => Some(c.0),
1748		Err(_) => {
1749			sp_runtime::print("Failed to decode compact u32 at:");
1750			sp_runtime::print(key);
1751			None
1752		},
1753	}
1754}