-
Notifications
You must be signed in to change notification settings - Fork 1.1k
pallet-referenda: Migrate from Currency reserves to fungible holds #10701
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
base: master
Are you sure you want to change the base?
Changes from all commits
c312c30
b3e6836
26431c0
ae8f38e
9d6e9b9
8d26843
0a4346d
8aa1740
2bf531f
426ae1a
0433400
58ba8b5
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change | ||||||||
|---|---|---|---|---|---|---|---|---|---|---|
|
|
@@ -73,12 +73,14 @@ use frame_support::{ | |||||||||
| dispatch::DispatchResult, | ||||||||||
| ensure, | ||||||||||
| traits::{ | ||||||||||
| fungible::{Balanced, Inspect, InspectHold, Mutate, MutateHold}, | ||||||||||
| schedule::{ | ||||||||||
| v3::{Anon as ScheduleAnon, Named as ScheduleNamed}, | ||||||||||
| DispatchTime, | ||||||||||
| }, | ||||||||||
| Currency, LockIdentifier, OnUnbalanced, OriginTrait, PollStatus, Polling, QueryPreimage, | ||||||||||
| ReservableCurrency, StorePreimage, VoteTally, | ||||||||||
| tokens::{Fortitude, Precision}, | ||||||||||
| LockIdentifier, OnUnbalanced, OriginTrait, PollStatus, Polling, QueryPreimage, | ||||||||||
| StorePreimage, VoteTally, | ||||||||||
| }, | ||||||||||
| BoundedVec, | ||||||||||
| }; | ||||||||||
|
|
@@ -97,11 +99,10 @@ use self::branch::{BeginDecidingBranch, OneFewerDecidingBranch, ServiceBranch}; | |||||||||
| pub use self::{ | ||||||||||
| pallet::*, | ||||||||||
| types::{ | ||||||||||
| BalanceOf, BlockNumberFor, BoundedCallOf, CallOf, ConstTrackInfo, Curve, DecidingStatus, | ||||||||||
| DecidingStatusOf, Deposit, InsertSorted, NegativeImbalanceOf, PalletsOriginOf, | ||||||||||
| ReferendumIndex, ReferendumInfo, ReferendumInfoOf, ReferendumStatus, ReferendumStatusOf, | ||||||||||
| ScheduleAddressOf, StringLike, TallyOf, Track, TrackIdOf, TrackInfo, TrackInfoOf, | ||||||||||
| TracksInfo, VotesOf, | ||||||||||
| BalanceOf, BlockNumberFor, BoundedCallOf, CallOf, ConstTrackInfo, Curve, DebtOf, | ||||||||||
| DecidingStatus, DecidingStatusOf, Deposit, InsertSorted, PalletsOriginOf, ReferendumIndex, | ||||||||||
| ReferendumInfo, ReferendumInfoOf, ReferendumStatus, ReferendumStatusOf, ScheduleAddressOf, | ||||||||||
| StringLike, TallyOf, Track, TrackIdOf, TrackInfo, TrackInfoOf, TracksInfo, VotesOf, | ||||||||||
| }, | ||||||||||
| weights::WeightInfo, | ||||||||||
| }; | ||||||||||
|
|
@@ -130,12 +131,20 @@ pub mod pallet { | |||||||||
| }; | ||||||||||
|
|
||||||||||
| /// The in-code storage version. | ||||||||||
| const STORAGE_VERSION: StorageVersion = StorageVersion::new(1); | ||||||||||
| const STORAGE_VERSION: StorageVersion = StorageVersion::new(2); | ||||||||||
|
|
||||||||||
| #[pallet::pallet] | ||||||||||
| #[pallet::storage_version(STORAGE_VERSION)] | ||||||||||
| pub struct Pallet<T, I = ()>(_); | ||||||||||
|
|
||||||||||
| /// A reason for holding funds. | ||||||||||
| /// Creates a hold reason for this pallet that is aggregated by `construct_runtime`. | ||||||||||
| #[pallet::composite_enum] | ||||||||||
| pub enum HoldReason<I: 'static = ()> { | ||||||||||
| /// The account has deposited tokens to place a decision deposit. | ||||||||||
| DecisionDeposit, | ||||||||||
| } | ||||||||||
|
|
||||||||||
| #[pallet::config] | ||||||||||
| pub trait Config<I: 'static = ()>: frame_system::Config + Sized { | ||||||||||
| // System level stuff. | ||||||||||
|
|
@@ -162,7 +171,11 @@ pub mod pallet { | |||||||||
| Hasher = Self::Hashing, | ||||||||||
| >; | ||||||||||
| /// Currency type for this pallet. | ||||||||||
| type Currency: ReservableCurrency<Self::AccountId>; | ||||||||||
| type NativeBalance: Inspect<Self::AccountId> | ||||||||||
| + Mutate<Self::AccountId> | ||||||||||
| + Balanced<Self::AccountId> | ||||||||||
| + InspectHold<Self::AccountId, Reason: From<HoldReason<I>>> | ||||||||||
| + MutateHold<Self::AccountId, Reason: From<HoldReason<I>>>; | ||||||||||
| // Origins and unbalances. | ||||||||||
| /// Origin from which proposals may be submitted. | ||||||||||
| type SubmitOrigin: EnsureOriginWithArg< | ||||||||||
|
|
@@ -175,7 +188,7 @@ pub mod pallet { | |||||||||
| /// 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 Slash: OnUnbalanced<DebtOf<Self, I>>; | ||||||||||
| /// The counting type for votes. Usually just balance. | ||||||||||
| type Votes: AtLeast32BitUnsigned + Copy + Parameter + Member + MaxEncodedLen; | ||||||||||
| /// The tallying type. | ||||||||||
|
|
@@ -569,7 +582,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, | ||||||||||
|
|
@@ -621,8 +634,8 @@ pub mod pallet { | |||||||||
| } | ||||||||||
| Self::note_one_fewer_deciding(status.track); | ||||||||||
| Self::deposit_event(Event::<T, I>::Killed { index, tally: status.tally }); | ||||||||||
| Self::slash_deposit(Some(status.submission_deposit.clone())); | ||||||||||
| Self::slash_deposit(status.decision_deposit.clone()); | ||||||||||
| Self::slash_deposit(Some(status.submission_deposit.clone()))?; | ||||||||||
| Self::slash_deposit(status.decision_deposit.clone())?; | ||||||||||
|
Comment on lines
+637
to
+638
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I don't really like that this can return an error here. We don't want to block the kill if for some reason the slash fails. Also
Suggested change
|
||||||||||
| Self::do_clear_metadata(index); | ||||||||||
| let info = ReferendumInfo::Killed(T::BlockNumberProvider::current_block_number()); | ||||||||||
| ReferendumInfoFor::<T, I>::insert(index, info); | ||||||||||
|
|
@@ -707,7 +720,7 @@ pub mod pallet { | |||||||||
| .take_submission_deposit() | ||||||||||
| .map_err(|_| Error::<T, I>::BadStatus)? | ||||||||||
| .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>::SubmissionDepositRefunded { | ||||||||||
| index, | ||||||||||
|
|
@@ -1289,23 +1302,40 @@ 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::NativeBalance::hold(&HoldReason::<I>::DecisionDeposit.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<(), DispatchError> { | ||||||||||
| if let Some(Deposit { who, amount }) = deposit { | ||||||||||
| T::Currency::unreserve(&who, amount); | ||||||||||
| T::NativeBalance::release( | ||||||||||
| &HoldReason::<I>::DecisionDeposit.into(), | ||||||||||
| &who, | ||||||||||
| amount, | ||||||||||
| Precision::BestEffort, | ||||||||||
| )?; | ||||||||||
| } | ||||||||||
| Ok(()) | ||||||||||
| } | ||||||||||
|
|
||||||||||
| /// Slash a deposit, if `Some`. | ||||||||||
| fn slash_deposit(deposit: Option<Deposit<T::AccountId, BalanceOf<T, I>>>) { | ||||||||||
| fn slash_deposit( | ||||||||||
| deposit: Option<Deposit<T::AccountId, BalanceOf<T, I>>>, | ||||||||||
| ) -> Result<(), DispatchError> { | ||||||||||
| 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 amount_burned = T::NativeBalance::burn_held( | ||||||||||
| &HoldReason::<I>::DecisionDeposit.into(), | ||||||||||
| &who, | ||||||||||
| amount, | ||||||||||
| Precision::BestEffort, | ||||||||||
| Fortitude::Force, | ||||||||||
| )?; | ||||||||||
| Self::deposit_event(Event::<T, I>::DepositSlashed { who, amount: amount_burned }); | ||||||||||
| } | ||||||||||
| Ok(()) | ||||||||||
| } | ||||||||||
|
|
||||||||||
| /// Determine whether the given `tally` would result in a referendum passing at `elapsed` blocks | ||||||||||
|
|
||||||||||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
IMO better to keep the same old name
Currency. It is still a kind of currency type, the underlying traits are fungible but this is fine. Most users won't see the difference as pallet-balances implements both. And if it breaks the compile error will be fine.