pallet_staking/pallet/mod.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//! Staking FRAME Pallet.
19
20use alloc::vec::Vec;
21use codec::Codec;
22use frame_election_provider_support::{ElectionProvider, SortedListProvider, VoteWeight};
23use frame_support::{
24 pallet_prelude::*,
25 traits::{
26 fungible::{
27 hold::{Balanced as FunHoldBalanced, Mutate as FunHoldMutate},
28 Mutate as FunMutate,
29 },
30 Contains, Defensive, EnsureOrigin, EstimateNextNewSession, Get, InspectLockableCurrency,
31 Nothing, OnUnbalanced, UnixTime,
32 },
33 weights::Weight,
34 BoundedVec,
35};
36use frame_system::{ensure_root, ensure_signed, pallet_prelude::*};
37use sp_runtime::{
38 traits::{SaturatedConversion, StaticLookup, Zero},
39 ArithmeticError, Perbill, Percent,
40};
41
42use sp_staking::{
43 EraIndex, Page, SessionIndex,
44 StakingAccount::{self, Controller, Stash},
45 StakingInterface,
46};
47
48mod impls;
49
50pub use impls::*;
51
52use crate::{
53 asset, slashing, weights::WeightInfo, AccountIdLookupOf, ActiveEraInfo, BalanceOf, EraPayout,
54 EraRewardPoints, Exposure, ExposurePage, Forcing, LedgerIntegrityState, MaxNominationsOf,
55 NegativeImbalanceOf, Nominations, NominationsQuota, PositiveImbalanceOf, RewardDestination,
56 SessionInterface, StakingLedger, UnappliedSlash, UnlockChunk, ValidatorPrefs,
57};
58
59// The speculative number of spans are used as an input of the weight annotation of
60// [`Call::unbond`], as the post dispatch weight may depend on the number of slashing span on the
61// account which is not provided as an input. The value set should be conservative but sensible.
62pub(crate) const SPECULATIVE_NUM_SPANS: u32 = 32;
63
64#[frame_support::pallet]
65pub mod pallet {
66 use super::*;
67 use codec::HasCompact;
68 use frame_election_provider_support::ElectionDataProvider;
69
70 use crate::{BenchmarkingConfig, PagedExposureMetadata};
71
72 /// The in-code storage version.
73 const STORAGE_VERSION: StorageVersion = StorageVersion::new(16);
74
75 #[pallet::pallet]
76 #[pallet::storage_version(STORAGE_VERSION)]
77 pub struct Pallet<T>(_);
78
79 /// Possible operations on the configuration values of this pallet.
80 #[derive(TypeInfo, Debug, Clone, Encode, Decode, DecodeWithMemTracking, PartialEq)]
81 pub enum ConfigOp<T: Default + Codec> {
82 /// Don't change.
83 Noop,
84 /// Set the given value.
85 Set(T),
86 /// Remove from storage.
87 Remove,
88 }
89
90 #[pallet::config(with_default)]
91 pub trait Config: frame_system::Config {
92 /// The old trait for staking balance. Deprecated and only used for migrating old ledgers.
93 #[pallet::no_default]
94 type OldCurrency: InspectLockableCurrency<
95 Self::AccountId,
96 Moment = BlockNumberFor<Self>,
97 Balance = Self::CurrencyBalance,
98 >;
99
100 /// The staking balance.
101 #[pallet::no_default]
102 type Currency: FunHoldMutate<
103 Self::AccountId,
104 Reason = Self::RuntimeHoldReason,
105 Balance = Self::CurrencyBalance,
106 > + FunMutate<Self::AccountId, Balance = Self::CurrencyBalance>
107 + FunHoldBalanced<Self::AccountId, Balance = Self::CurrencyBalance>;
108
109 /// Overarching hold reason.
110 #[pallet::no_default_bounds]
111 type RuntimeHoldReason: From<HoldReason>;
112
113 /// Just the `Currency::Balance` type; we have this item to allow us to constrain it to
114 /// `From<u64>`.
115 type CurrencyBalance: sp_runtime::traits::AtLeast32BitUnsigned
116 + codec::FullCodec
117 + DecodeWithMemTracking
118 + HasCompact<Type: DecodeWithMemTracking>
119 + Copy
120 + MaybeSerializeDeserialize
121 + core::fmt::Debug
122 + Default
123 + From<u64>
124 + TypeInfo
125 + Send
126 + Sync
127 + MaxEncodedLen;
128 /// Time used for computing era duration.
129 ///
130 /// It is guaranteed to start being called from the first `on_finalize`. Thus value at
131 /// genesis is not used.
132 #[pallet::no_default]
133 type UnixTime: UnixTime;
134
135 /// Convert a balance into a number used for election calculation. This must fit into a
136 /// `u64` but is allowed to be sensibly lossy. The `u64` is used to communicate with the
137 /// [`frame_election_provider_support`] crate which accepts u64 numbers and does operations
138 /// in 128.
139 /// Consequently, the backward convert is used convert the u128s from sp-elections back to a
140 /// [`BalanceOf`].
141 #[pallet::no_default_bounds]
142 type CurrencyToVote: sp_staking::currency_to_vote::CurrencyToVote<BalanceOf<Self>>;
143
144 /// Something that provides the election functionality.
145 #[pallet::no_default]
146 type ElectionProvider: ElectionProvider<
147 AccountId = Self::AccountId,
148 BlockNumber = BlockNumberFor<Self>,
149 // we only accept an election provider that has staking as data provider.
150 DataProvider = Pallet<Self>,
151 >;
152 /// Something that provides the election functionality at genesis.
153 #[pallet::no_default]
154 type GenesisElectionProvider: ElectionProvider<
155 AccountId = Self::AccountId,
156 BlockNumber = BlockNumberFor<Self>,
157 DataProvider = Pallet<Self>,
158 >;
159
160 /// Something that defines the maximum number of nominations per nominator.
161 #[pallet::no_default_bounds]
162 type NominationsQuota: NominationsQuota<BalanceOf<Self>>;
163
164 /// Number of eras to keep in history.
165 ///
166 /// Following information is kept for eras in `[current_era -
167 /// HistoryDepth, current_era]`: `ErasStakers`, `ErasStakersClipped`,
168 /// `ErasValidatorPrefs`, `ErasValidatorReward`, `ErasRewardPoints`,
169 /// `ErasTotalStake`, `ErasStartSessionIndex`, `ClaimedRewards`, `ErasStakersPaged`,
170 /// `ErasStakersOverview`.
171 ///
172 /// Must be more than the number of eras delayed by session.
173 /// I.e. active era must always be in history. I.e. `active_era >
174 /// current_era - history_depth` must be guaranteed.
175 ///
176 /// If migrating an existing pallet from storage value to config value,
177 /// this should be set to same value or greater as in storage.
178 ///
179 /// Note: `HistoryDepth` is used as the upper bound for the `BoundedVec`
180 /// item `StakingLedger.legacy_claimed_rewards`. Setting this value lower than
181 /// the existing value can lead to inconsistencies in the
182 /// `StakingLedger` and will need to be handled properly in a migration.
183 /// The test `reducing_history_depth_abrupt` shows this effect.
184 #[pallet::constant]
185 type HistoryDepth: Get<u32>;
186
187 /// Tokens have been minted and are unused for validator-reward.
188 /// See [Era payout](./index.html#era-payout).
189 #[pallet::no_default_bounds]
190 type RewardRemainder: OnUnbalanced<NegativeImbalanceOf<Self>>;
191
192 /// The overarching event type.
193 #[pallet::no_default_bounds]
194 #[allow(deprecated)]
195 type RuntimeEvent: From<Event<Self>> + IsType<<Self as frame_system::Config>::RuntimeEvent>;
196
197 /// Handler for the unbalanced reduction when slashing a staker.
198 #[pallet::no_default_bounds]
199 type Slash: OnUnbalanced<NegativeImbalanceOf<Self>>;
200
201 /// Handler for the unbalanced increment when rewarding a staker.
202 /// NOTE: in most cases, the implementation of `OnUnbalanced` should modify the total
203 /// issuance.
204 #[pallet::no_default_bounds]
205 type Reward: OnUnbalanced<PositiveImbalanceOf<Self>>;
206
207 /// Number of sessions per era.
208 #[pallet::constant]
209 type SessionsPerEra: Get<SessionIndex>;
210
211 /// Number of eras that staked funds must remain bonded for.
212 #[pallet::constant]
213 type BondingDuration: Get<EraIndex>;
214
215 /// Number of eras that slashes are deferred by, after computation.
216 ///
217 /// This should be less than the bonding duration. Set to 0 if slashes
218 /// should be applied immediately, without opportunity for intervention.
219 #[pallet::constant]
220 type SlashDeferDuration: Get<EraIndex>;
221
222 /// The origin which can manage less critical staking parameters that does not require root.
223 ///
224 /// Supported actions: (1) cancel deferred slash, (2) set minimum commission.
225 #[pallet::no_default]
226 type AdminOrigin: EnsureOrigin<Self::RuntimeOrigin>;
227
228 /// Interface for interacting with a session pallet.
229 type SessionInterface: SessionInterface<Self::AccountId>;
230
231 /// The payout for validators and the system for the current era.
232 /// See [Era payout](./index.html#era-payout).
233 #[pallet::no_default]
234 type EraPayout: EraPayout<BalanceOf<Self>>;
235
236 /// Something that can estimate the next session change, accurately or as a best effort
237 /// guess.
238 #[pallet::no_default_bounds]
239 type NextNewSession: EstimateNextNewSession<BlockNumberFor<Self>>;
240
241 /// The maximum size of each `T::ExposurePage`.
242 ///
243 /// An `ExposurePage` is weakly bounded to a maximum of `MaxExposurePageSize`
244 /// nominators.
245 ///
246 /// For older non-paged exposure, a reward payout was restricted to the top
247 /// `MaxExposurePageSize` nominators. This is to limit the i/o cost for the
248 /// nominator payout.
249 ///
250 /// Note: `MaxExposurePageSize` is used to bound `ClaimedRewards` and is unsafe to reduce
251 /// without handling it in a migration.
252 #[pallet::constant]
253 type MaxExposurePageSize: Get<u32>;
254
255 /// The absolute maximum of winner validators this pallet should return.
256 #[pallet::constant]
257 type MaxValidatorSet: Get<u32>;
258
259 /// Something that provides a best-effort sorted list of voters aka electing nominators,
260 /// used for NPoS election.
261 ///
262 /// The changes to nominators are reported to this. Moreover, each validator's self-vote is
263 /// also reported as one independent vote.
264 ///
265 /// To keep the load off the chain as much as possible, changes made to the staked amount
266 /// via rewards and slashes are not reported and thus need to be manually fixed by the
267 /// staker. In case of `bags-list`, this always means using `rebag` and `putInFrontOf`.
268 ///
269 /// Invariant: what comes out of this list will always be a nominator.
270 #[pallet::no_default]
271 type VoterList: SortedListProvider<Self::AccountId, Score = VoteWeight>;
272
273 /// WIP: This is a noop as of now, the actual business logic that's described below is going
274 /// to be introduced in a follow-up PR.
275 ///
276 /// Something that provides a best-effort sorted list of targets aka electable validators,
277 /// used for NPoS election.
278 ///
279 /// The changes to the approval stake of each validator are reported to this. This means any
280 /// change to:
281 /// 1. The stake of any validator or nominator.
282 /// 2. The targets of any nominator
283 /// 3. The role of any staker (e.g. validator -> chilled, nominator -> validator, etc)
284 ///
285 /// Unlike `VoterList`, the values in this list are always kept up to date with reward and
286 /// slash as well, and thus represent the accurate approval stake of all account being
287 /// nominated by nominators.
288 ///
289 /// Note that while at the time of nomination, all targets are checked to be real
290 /// validators, they can chill at any point, and their approval stakes will still be
291 /// recorded. This implies that what comes out of iterating this list MIGHT NOT BE AN ACTIVE
292 /// VALIDATOR.
293 #[pallet::no_default]
294 type TargetList: SortedListProvider<Self::AccountId, Score = BalanceOf<Self>>;
295
296 /// The maximum number of `unlocking` chunks a [`StakingLedger`] can
297 /// have. Effectively determines how many unique eras a staker may be
298 /// unbonding in.
299 ///
300 /// Note: `MaxUnlockingChunks` is used as the upper bound for the
301 /// `BoundedVec` item `StakingLedger.unlocking`. Setting this value
302 /// lower than the existing value can lead to inconsistencies in the
303 /// `StakingLedger` and will need to be handled properly in a runtime
304 /// migration. The test `reducing_max_unlocking_chunks_abrupt` shows
305 /// this effect.
306 #[pallet::constant]
307 type MaxUnlockingChunks: Get<u32>;
308
309 /// The maximum amount of controller accounts that can be deprecated in one call.
310 type MaxControllersInDeprecationBatch: Get<u32>;
311
312 /// Something that listens to staking updates and performs actions based on the data it
313 /// receives.
314 ///
315 /// WARNING: this only reports slashing and withdraw events for the time being.
316 #[pallet::no_default_bounds]
317 type EventListeners: sp_staking::OnStakingUpdate<Self::AccountId, BalanceOf<Self>>;
318
319 #[pallet::no_default_bounds]
320 /// Filter some accounts from participating in staking.
321 ///
322 /// This is useful for example to blacklist an account that is participating in staking in
323 /// another way (such as pools).
324 type Filter: Contains<Self::AccountId>;
325
326 /// Some parameters of the benchmarking.
327 #[cfg(feature = "std")]
328 type BenchmarkingConfig: BenchmarkingConfig;
329
330 #[cfg(not(feature = "std"))]
331 #[pallet::no_default]
332 type BenchmarkingConfig: BenchmarkingConfig;
333
334 /// Weight information for extrinsics in this pallet.
335 type WeightInfo: WeightInfo;
336 }
337
338 /// A reason for placing a hold on funds.
339 #[pallet::composite_enum]
340 pub enum HoldReason {
341 /// Funds on stake by a nominator or a validator.
342 #[codec(index = 0)]
343 Staking,
344 }
345
346 /// Default implementations of [`DefaultConfig`], which can be used to implement [`Config`].
347 pub mod config_preludes {
348 use super::*;
349 use frame_support::{derive_impl, parameter_types, traits::ConstU32};
350 pub struct TestDefaultConfig;
351
352 #[derive_impl(frame_system::config_preludes::TestDefaultConfig, no_aggregated_types)]
353 impl frame_system::DefaultConfig for TestDefaultConfig {}
354
355 parameter_types! {
356 pub const SessionsPerEra: SessionIndex = 3;
357 pub const BondingDuration: EraIndex = 3;
358 }
359
360 #[frame_support::register_default_impl(TestDefaultConfig)]
361 impl DefaultConfig for TestDefaultConfig {
362 #[inject_runtime_type]
363 type RuntimeEvent = ();
364 #[inject_runtime_type]
365 type RuntimeHoldReason = ();
366 type CurrencyBalance = u128;
367 type CurrencyToVote = ();
368 type NominationsQuota = crate::FixedNominationsQuota<16>;
369 type HistoryDepth = ConstU32<84>;
370 type RewardRemainder = ();
371 type Slash = ();
372 type Reward = ();
373 type SessionsPerEra = SessionsPerEra;
374 type BondingDuration = BondingDuration;
375 type SlashDeferDuration = ();
376 type SessionInterface = ();
377 type NextNewSession = ();
378 type MaxExposurePageSize = ConstU32<64>;
379 type MaxUnlockingChunks = ConstU32<32>;
380 type MaxValidatorSet = ConstU32<100>;
381 type MaxControllersInDeprecationBatch = ConstU32<100>;
382 type EventListeners = ();
383 type Filter = Nothing;
384 #[cfg(feature = "std")]
385 type BenchmarkingConfig = crate::TestBenchmarkingConfig;
386 type WeightInfo = ();
387 }
388 }
389
390 /// The ideal number of active validators.
391 #[pallet::storage]
392 pub type ValidatorCount<T> = StorageValue<_, u32, ValueQuery>;
393
394 /// Minimum number of staking participants before emergency conditions are imposed.
395 #[pallet::storage]
396 pub type MinimumValidatorCount<T> = StorageValue<_, u32, ValueQuery>;
397
398 /// Any validators that may never be slashed or forcibly kicked. It's a Vec since they're
399 /// easy to initialize and the performance hit is minimal (we expect no more than four
400 /// invulnerables) and restricted to testnets.
401 #[pallet::storage]
402 #[pallet::unbounded]
403 pub type Invulnerables<T: Config> = StorageValue<_, Vec<T::AccountId>, ValueQuery>;
404
405 /// Map from all locked "stash" accounts to the controller account.
406 ///
407 /// TWOX-NOTE: SAFE since `AccountId` is a secure hash.
408 #[pallet::storage]
409 pub type Bonded<T: Config> = StorageMap<_, Twox64Concat, T::AccountId, T::AccountId>;
410
411 /// The minimum active bond to become and maintain the role of a nominator.
412 #[pallet::storage]
413 pub type MinNominatorBond<T: Config> = StorageValue<_, BalanceOf<T>, ValueQuery>;
414
415 /// The minimum active bond to become and maintain the role of a validator.
416 #[pallet::storage]
417 pub type MinValidatorBond<T: Config> = StorageValue<_, BalanceOf<T>, ValueQuery>;
418
419 /// The minimum active nominator stake of the last successful election.
420 #[pallet::storage]
421 pub type MinimumActiveStake<T> = StorageValue<_, BalanceOf<T>, ValueQuery>;
422
423 /// The minimum amount of commission that validators can set.
424 ///
425 /// If set to `0`, no limit exists.
426 #[pallet::storage]
427 pub type MinCommission<T: Config> = StorageValue<_, Perbill, ValueQuery>;
428
429 /// Map from all (unlocked) "controller" accounts to the info regarding the staking.
430 ///
431 /// Note: All the reads and mutations to this storage *MUST* be done through the methods exposed
432 /// by [`StakingLedger`] to ensure data and lock consistency.
433 #[pallet::storage]
434 pub type Ledger<T: Config> = StorageMap<_, Blake2_128Concat, T::AccountId, StakingLedger<T>>;
435
436 /// Where the reward payment should be made. Keyed by stash.
437 ///
438 /// TWOX-NOTE: SAFE since `AccountId` is a secure hash.
439 #[pallet::storage]
440 pub type Payee<T: Config> =
441 StorageMap<_, Twox64Concat, T::AccountId, RewardDestination<T::AccountId>, OptionQuery>;
442
443 /// The map from (wannabe) validator stash key to the preferences of that validator.
444 ///
445 /// TWOX-NOTE: SAFE since `AccountId` is a secure hash.
446 #[pallet::storage]
447 pub type Validators<T: Config> =
448 CountedStorageMap<_, Twox64Concat, T::AccountId, ValidatorPrefs, ValueQuery>;
449
450 /// The maximum validator count before we stop allowing new validators to join.
451 ///
452 /// When this value is not set, no limits are enforced.
453 #[pallet::storage]
454 pub type MaxValidatorsCount<T> = StorageValue<_, u32, OptionQuery>;
455
456 /// The map from nominator stash key to their nomination preferences, namely the validators that
457 /// they wish to support.
458 ///
459 /// Note that the keys of this storage map might become non-decodable in case the
460 /// account's [`NominationsQuota::MaxNominations`] configuration is decreased.
461 /// In this rare case, these nominators
462 /// are still existent in storage, their key is correct and retrievable (i.e. `contains_key`
463 /// indicates that they exist), but their value cannot be decoded. Therefore, the non-decodable
464 /// nominators will effectively not-exist, until they re-submit their preferences such that it
465 /// is within the bounds of the newly set `Config::MaxNominations`.
466 ///
467 /// This implies that `::iter_keys().count()` and `::iter().count()` might return different
468 /// values for this map. Moreover, the main `::count()` is aligned with the former, namely the
469 /// number of keys that exist.
470 ///
471 /// Lastly, if any of the nominators become non-decodable, they can be chilled immediately via
472 /// [`Call::chill_other`] dispatchable by anyone.
473 ///
474 /// TWOX-NOTE: SAFE since `AccountId` is a secure hash.
475 #[pallet::storage]
476 pub type Nominators<T: Config> =
477 CountedStorageMap<_, Twox64Concat, T::AccountId, Nominations<T>>;
478
479 /// Stakers whose funds are managed by other pallets.
480 ///
481 /// This pallet does not apply any locks on them, therefore they are only virtually bonded. They
482 /// are expected to be keyless accounts and hence should not be allowed to mutate their ledger
483 /// directly via this pallet. Instead, these accounts are managed by other pallets and accessed
484 /// via low level apis. We keep track of them to do minimal integrity checks.
485 #[pallet::storage]
486 pub type VirtualStakers<T: Config> = CountedStorageMap<_, Twox64Concat, T::AccountId, ()>;
487
488 /// The maximum nominator count before we stop allowing new validators to join.
489 ///
490 /// When this value is not set, no limits are enforced.
491 #[pallet::storage]
492 pub type MaxNominatorsCount<T> = StorageValue<_, u32, OptionQuery>;
493
494 /// The current era index.
495 ///
496 /// This is the latest planned era, depending on how the Session pallet queues the validator
497 /// set, it might be active or not.
498 #[pallet::storage]
499 pub type CurrentEra<T> = StorageValue<_, EraIndex>;
500
501 /// The active era information, it holds index and start.
502 ///
503 /// The active era is the era being currently rewarded. Validator set of this era must be
504 /// equal to [`SessionInterface::validators`].
505 #[pallet::storage]
506 pub type ActiveEra<T> = StorageValue<_, ActiveEraInfo>;
507
508 /// The session index at which the era start for the last [`Config::HistoryDepth`] eras.
509 ///
510 /// Note: This tracks the starting session (i.e. session index when era start being active)
511 /// for the eras in `[CurrentEra - HISTORY_DEPTH, CurrentEra]`.
512 #[pallet::storage]
513 pub type ErasStartSessionIndex<T> = StorageMap<_, Twox64Concat, EraIndex, SessionIndex>;
514
515 /// Exposure of validator at era.
516 ///
517 /// This is keyed first by the era index to allow bulk deletion and then the stash account.
518 ///
519 /// Is it removed after [`Config::HistoryDepth`] eras.
520 /// If stakers hasn't been set or has been removed then empty exposure is returned.
521 ///
522 /// Note: Deprecated since v14. Use `EraInfo` instead to work with exposures.
523 #[pallet::storage]
524 #[pallet::unbounded]
525 pub type ErasStakers<T: Config> = StorageDoubleMap<
526 _,
527 Twox64Concat,
528 EraIndex,
529 Twox64Concat,
530 T::AccountId,
531 Exposure<T::AccountId, BalanceOf<T>>,
532 ValueQuery,
533 >;
534
535 /// Summary of validator exposure at a given era.
536 ///
537 /// This contains the total stake in support of the validator and their own stake. In addition,
538 /// it can also be used to get the number of nominators backing this validator and the number of
539 /// exposure pages they are divided into. The page count is useful to determine the number of
540 /// pages of rewards that needs to be claimed.
541 ///
542 /// This is keyed first by the era index to allow bulk deletion and then the stash account.
543 /// Should only be accessed through `EraInfo`.
544 ///
545 /// Is it removed after [`Config::HistoryDepth`] eras.
546 /// If stakers hasn't been set or has been removed then empty overview is returned.
547 #[pallet::storage]
548 pub type ErasStakersOverview<T: Config> = StorageDoubleMap<
549 _,
550 Twox64Concat,
551 EraIndex,
552 Twox64Concat,
553 T::AccountId,
554 PagedExposureMetadata<BalanceOf<T>>,
555 OptionQuery,
556 >;
557
558 /// Clipped Exposure of validator at era.
559 ///
560 /// Note: This is deprecated, should be used as read-only and will be removed in the future.
561 /// New `Exposure`s are stored in a paged manner in `ErasStakersPaged` instead.
562 ///
563 /// This is similar to [`ErasStakers`] but number of nominators exposed is reduced to the
564 /// `T::MaxExposurePageSize` biggest stakers.
565 /// (Note: the field `total` and `own` of the exposure remains unchanged).
566 /// This is used to limit the i/o cost for the nominator payout.
567 ///
568 /// This is keyed fist by the era index to allow bulk deletion and then the stash account.
569 ///
570 /// It is removed after [`Config::HistoryDepth`] eras.
571 /// If stakers hasn't been set or has been removed then empty exposure is returned.
572 ///
573 /// Note: Deprecated since v14. Use `EraInfo` instead to work with exposures.
574 #[pallet::storage]
575 #[pallet::unbounded]
576 pub type ErasStakersClipped<T: Config> = StorageDoubleMap<
577 _,
578 Twox64Concat,
579 EraIndex,
580 Twox64Concat,
581 T::AccountId,
582 Exposure<T::AccountId, BalanceOf<T>>,
583 ValueQuery,
584 >;
585
586 /// Paginated exposure of a validator at given era.
587 ///
588 /// This is keyed first by the era index to allow bulk deletion, then stash account and finally
589 /// the page. Should only be accessed through `EraInfo`.
590 ///
591 /// This is cleared after [`Config::HistoryDepth`] eras.
592 #[pallet::storage]
593 #[pallet::unbounded]
594 pub type ErasStakersPaged<T: Config> = StorageNMap<
595 _,
596 (
597 NMapKey<Twox64Concat, EraIndex>,
598 NMapKey<Twox64Concat, T::AccountId>,
599 NMapKey<Twox64Concat, Page>,
600 ),
601 ExposurePage<T::AccountId, BalanceOf<T>>,
602 OptionQuery,
603 >;
604
605 /// History of claimed paged rewards by era and validator.
606 ///
607 /// This is keyed by era and validator stash which maps to the set of page indexes which have
608 /// been claimed.
609 ///
610 /// It is removed after [`Config::HistoryDepth`] eras.
611 #[pallet::storage]
612 #[pallet::unbounded]
613 pub type ClaimedRewards<T: Config> = StorageDoubleMap<
614 _,
615 Twox64Concat,
616 EraIndex,
617 Twox64Concat,
618 T::AccountId,
619 Vec<Page>,
620 ValueQuery,
621 >;
622
623 /// Similar to `ErasStakers`, this holds the preferences of validators.
624 ///
625 /// This is keyed first by the era index to allow bulk deletion and then the stash account.
626 ///
627 /// Is it removed after [`Config::HistoryDepth`] eras.
628 // If prefs hasn't been set or has been removed then 0 commission is returned.
629 #[pallet::storage]
630 pub type ErasValidatorPrefs<T: Config> = StorageDoubleMap<
631 _,
632 Twox64Concat,
633 EraIndex,
634 Twox64Concat,
635 T::AccountId,
636 ValidatorPrefs,
637 ValueQuery,
638 >;
639
640 /// The total validator era payout for the last [`Config::HistoryDepth`] eras.
641 ///
642 /// Eras that haven't finished yet or has been removed doesn't have reward.
643 #[pallet::storage]
644 pub type ErasValidatorReward<T: Config> = StorageMap<_, Twox64Concat, EraIndex, BalanceOf<T>>;
645
646 /// Rewards for the last [`Config::HistoryDepth`] eras.
647 /// If reward hasn't been set or has been removed then 0 reward is returned.
648 #[pallet::storage]
649 #[pallet::unbounded]
650 pub type ErasRewardPoints<T: Config> =
651 StorageMap<_, Twox64Concat, EraIndex, EraRewardPoints<T::AccountId>, ValueQuery>;
652
653 /// The total amount staked for the last [`Config::HistoryDepth`] eras.
654 /// If total hasn't been set or has been removed then 0 stake is returned.
655 #[pallet::storage]
656 pub type ErasTotalStake<T: Config> =
657 StorageMap<_, Twox64Concat, EraIndex, BalanceOf<T>, ValueQuery>;
658
659 /// Mode of era forcing.
660 #[pallet::storage]
661 pub type ForceEra<T> = StorageValue<_, Forcing, ValueQuery>;
662
663 /// Maximum staked rewards, i.e. the percentage of the era inflation that
664 /// is used for stake rewards.
665 /// See [Era payout](./index.html#era-payout).
666 #[pallet::storage]
667 pub type MaxStakedRewards<T> = StorageValue<_, Percent, OptionQuery>;
668
669 /// The percentage of the slash that is distributed to reporters.
670 ///
671 /// The rest of the slashed value is handled by the `Slash`.
672 #[pallet::storage]
673 pub type SlashRewardFraction<T> = StorageValue<_, Perbill, ValueQuery>;
674
675 /// The amount of currency given to reporters of a slash event which was
676 /// canceled by extraordinary circumstances (e.g. governance).
677 #[pallet::storage]
678 pub type CanceledSlashPayout<T: Config> = StorageValue<_, BalanceOf<T>, ValueQuery>;
679
680 /// All unapplied slashes that are queued for later.
681 #[pallet::storage]
682 #[pallet::unbounded]
683 pub type UnappliedSlashes<T: Config> = StorageMap<
684 _,
685 Twox64Concat,
686 EraIndex,
687 Vec<UnappliedSlash<T::AccountId, BalanceOf<T>>>,
688 ValueQuery,
689 >;
690
691 /// A mapping from still-bonded eras to the first session index of that era.
692 ///
693 /// Must contains information for eras for the range:
694 /// `[active_era - bounding_duration; active_era]`
695 #[pallet::storage]
696 #[pallet::unbounded]
697 pub type BondedEras<T: Config> = StorageValue<_, Vec<(EraIndex, SessionIndex)>, ValueQuery>;
698
699 /// All slashing events on validators, mapped by era to the highest slash proportion
700 /// and slash value of the era.
701 #[pallet::storage]
702 pub type ValidatorSlashInEra<T: Config> = StorageDoubleMap<
703 _,
704 Twox64Concat,
705 EraIndex,
706 Twox64Concat,
707 T::AccountId,
708 (Perbill, BalanceOf<T>),
709 >;
710
711 /// All slashing events on nominators, mapped by era to the highest slash value of the era.
712 #[pallet::storage]
713 pub type NominatorSlashInEra<T: Config> =
714 StorageDoubleMap<_, Twox64Concat, EraIndex, Twox64Concat, T::AccountId, BalanceOf<T>>;
715
716 /// Slashing spans for stash accounts.
717 #[pallet::storage]
718 #[pallet::unbounded]
719 pub type SlashingSpans<T: Config> =
720 StorageMap<_, Twox64Concat, T::AccountId, slashing::SlashingSpans>;
721
722 /// Records information about the maximum slash of a stash within a slashing span,
723 /// as well as how much reward has been paid out.
724 #[pallet::storage]
725 pub type SpanSlash<T: Config> = StorageMap<
726 _,
727 Twox64Concat,
728 (T::AccountId, slashing::SpanIndex),
729 slashing::SpanRecord<BalanceOf<T>>,
730 ValueQuery,
731 >;
732
733 /// The last planned session scheduled by the session pallet.
734 ///
735 /// This is basically in sync with the call to [`pallet_session::SessionManager::new_session`].
736 #[pallet::storage]
737 pub type CurrentPlannedSession<T> = StorageValue<_, SessionIndex, ValueQuery>;
738
739 /// The threshold for when users can start calling `chill_other` for other validators /
740 /// nominators. The threshold is compared to the actual number of validators / nominators
741 /// (`CountFor*`) in the system compared to the configured max (`Max*Count`).
742 #[pallet::storage]
743 pub type ChillThreshold<T: Config> = StorageValue<_, Percent, OptionQuery>;
744
745 #[pallet::genesis_config]
746 #[derive(frame_support::DefaultNoBound)]
747 pub struct GenesisConfig<T: Config> {
748 pub validator_count: u32,
749 pub minimum_validator_count: u32,
750 pub invulnerables: Vec<T::AccountId>,
751 pub force_era: Forcing,
752 pub slash_reward_fraction: Perbill,
753 pub canceled_payout: BalanceOf<T>,
754 pub stakers:
755 Vec<(T::AccountId, T::AccountId, BalanceOf<T>, crate::StakerStatus<T::AccountId>)>,
756 pub min_nominator_bond: BalanceOf<T>,
757 pub min_validator_bond: BalanceOf<T>,
758 pub max_validator_count: Option<u32>,
759 pub max_nominator_count: Option<u32>,
760 }
761
762 #[pallet::genesis_build]
763 impl<T: Config> BuildGenesisConfig for GenesisConfig<T> {
764 fn build(&self) {
765 ValidatorCount::<T>::put(self.validator_count);
766 MinimumValidatorCount::<T>::put(self.minimum_validator_count);
767 Invulnerables::<T>::put(&self.invulnerables);
768 ForceEra::<T>::put(self.force_era);
769 CanceledSlashPayout::<T>::put(self.canceled_payout);
770 SlashRewardFraction::<T>::put(self.slash_reward_fraction);
771 MinNominatorBond::<T>::put(self.min_nominator_bond);
772 MinValidatorBond::<T>::put(self.min_validator_bond);
773 if let Some(x) = self.max_validator_count {
774 MaxValidatorsCount::<T>::put(x);
775 }
776 if let Some(x) = self.max_nominator_count {
777 MaxNominatorsCount::<T>::put(x);
778 }
779
780 for &(ref stash, _, balance, ref status) in &self.stakers {
781 crate::log!(
782 trace,
783 "inserting genesis staker: {:?} => {:?} => {:?}",
784 stash,
785 balance,
786 status
787 );
788 assert!(
789 asset::free_to_stake::<T>(stash) >= balance,
790 "Stash does not have enough balance to bond."
791 );
792 frame_support::assert_ok!(<Pallet<T>>::bond(
793 T::RuntimeOrigin::from(Some(stash.clone()).into()),
794 balance,
795 RewardDestination::Staked,
796 ));
797 frame_support::assert_ok!(match status {
798 crate::StakerStatus::Validator => <Pallet<T>>::validate(
799 T::RuntimeOrigin::from(Some(stash.clone()).into()),
800 Default::default(),
801 ),
802 crate::StakerStatus::Nominator(votes) => <Pallet<T>>::nominate(
803 T::RuntimeOrigin::from(Some(stash.clone()).into()),
804 votes.iter().map(|l| T::Lookup::unlookup(l.clone())).collect(),
805 ),
806 _ => Ok(()),
807 });
808 assert!(
809 ValidatorCount::<T>::get() <=
810 <T::ElectionProvider as ElectionProvider>::MaxWinnersPerPage::get() *
811 <T::ElectionProvider as ElectionProvider>::Pages::get()
812 );
813 }
814
815 // all voters are reported to the `VoterList`.
816 assert_eq!(
817 T::VoterList::count(),
818 Nominators::<T>::count() + Validators::<T>::count(),
819 "not all genesis stakers were inserted into sorted list provider, something is wrong."
820 );
821 }
822 }
823
824 #[pallet::event]
825 #[pallet::generate_deposit(pub(crate) fn deposit_event)]
826 pub enum Event<T: Config> {
827 /// The era payout has been set; the first balance is the validator-payout; the second is
828 /// the remainder from the maximum amount of reward.
829 EraPaid { era_index: EraIndex, validator_payout: BalanceOf<T>, remainder: BalanceOf<T> },
830 /// The nominator has been rewarded by this amount to this destination.
831 Rewarded {
832 stash: T::AccountId,
833 dest: RewardDestination<T::AccountId>,
834 amount: BalanceOf<T>,
835 },
836 /// A staker (validator or nominator) has been slashed by the given amount.
837 Slashed { staker: T::AccountId, amount: BalanceOf<T> },
838 /// A slash for the given validator, for the given percentage of their stake, at the given
839 /// era as been reported.
840 SlashReported { validator: T::AccountId, fraction: Perbill, slash_era: EraIndex },
841 /// An old slashing report from a prior era was discarded because it could
842 /// not be processed.
843 OldSlashingReportDiscarded { session_index: SessionIndex },
844 /// A new set of stakers was elected.
845 StakersElected,
846 /// An account has bonded this amount. \[stash, amount\]
847 ///
848 /// NOTE: This event is only emitted when funds are bonded via a dispatchable. Notably,
849 /// it will not be emitted for staking rewards when they are added to stake.
850 Bonded { stash: T::AccountId, amount: BalanceOf<T> },
851 /// An account has unbonded this amount.
852 Unbonded { stash: T::AccountId, amount: BalanceOf<T> },
853 /// An account has called `withdraw_unbonded` and removed unbonding chunks worth `Balance`
854 /// from the unlocking queue.
855 Withdrawn { stash: T::AccountId, amount: BalanceOf<T> },
856 /// A nominator has been kicked from a validator.
857 Kicked { nominator: T::AccountId, stash: T::AccountId },
858 /// The election failed. No new era is planned.
859 StakingElectionFailed,
860 /// An account has stopped participating as either a validator or nominator.
861 Chilled { stash: T::AccountId },
862 /// A Page of stakers rewards are getting paid. `next` is `None` if all pages are claimed.
863 PayoutStarted {
864 era_index: EraIndex,
865 validator_stash: T::AccountId,
866 page: Page,
867 next: Option<Page>,
868 },
869 /// A validator has set their preferences.
870 ValidatorPrefsSet { stash: T::AccountId, prefs: ValidatorPrefs },
871 /// Voters size limit reached.
872 SnapshotVotersSizeExceeded { size: u32 },
873 /// Targets size limit reached.
874 SnapshotTargetsSizeExceeded { size: u32 },
875 /// A new force era mode was set.
876 ForceEra { mode: Forcing },
877 /// Report of a controller batch deprecation.
878 ControllerBatchDeprecated { failures: u32 },
879 /// Staking balance migrated from locks to holds, with any balance that could not be held
880 /// is force withdrawn.
881 CurrencyMigrated { stash: T::AccountId, force_withdraw: BalanceOf<T> },
882 }
883
884 #[pallet::error]
885 #[derive(PartialEq)]
886 pub enum Error<T> {
887 /// Not a controller account.
888 NotController,
889 /// Not a stash account.
890 NotStash,
891 /// Stash is already bonded.
892 AlreadyBonded,
893 /// Controller is already paired.
894 AlreadyPaired,
895 /// Targets cannot be empty.
896 EmptyTargets,
897 /// Duplicate index.
898 DuplicateIndex,
899 /// Slash record index out of bounds.
900 InvalidSlashIndex,
901 /// Cannot have a validator or nominator role, with value less than the minimum defined by
902 /// governance (see `MinValidatorBond` and `MinNominatorBond`). If unbonding is the
903 /// intention, `chill` first to remove one's role as validator/nominator.
904 InsufficientBond,
905 /// Can not schedule more unlock chunks.
906 NoMoreChunks,
907 /// Can not rebond without unlocking chunks.
908 NoUnlockChunk,
909 /// Attempting to target a stash that still has funds.
910 FundedTarget,
911 /// Invalid era to reward.
912 InvalidEraToReward,
913 /// Invalid number of nominations.
914 InvalidNumberOfNominations,
915 /// Items are not sorted and unique.
916 NotSortedAndUnique,
917 /// Rewards for this era have already been claimed for this validator.
918 AlreadyClaimed,
919 /// No nominators exist on this page.
920 InvalidPage,
921 /// Incorrect previous history depth input provided.
922 IncorrectHistoryDepth,
923 /// Incorrect number of slashing spans provided.
924 IncorrectSlashingSpans,
925 /// Internal state has become somehow corrupted and the operation cannot continue.
926 BadState,
927 /// Too many nomination targets supplied.
928 TooManyTargets,
929 /// A nomination target was supplied that was blocked or otherwise not a validator.
930 BadTarget,
931 /// The user has enough bond and thus cannot be chilled forcefully by an external person.
932 CannotChillOther,
933 /// There are too many nominators in the system. Governance needs to adjust the staking
934 /// settings to keep things safe for the runtime.
935 TooManyNominators,
936 /// There are too many validator candidates in the system. Governance needs to adjust the
937 /// staking settings to keep things safe for the runtime.
938 TooManyValidators,
939 /// Commission is too low. Must be at least `MinCommission`.
940 CommissionTooLow,
941 /// Some bound is not met.
942 BoundNotMet,
943 /// Used when attempting to use deprecated controller account logic.
944 ControllerDeprecated,
945 /// Cannot reset a ledger.
946 CannotRestoreLedger,
947 /// Provided reward destination is not allowed.
948 RewardDestinationRestricted,
949 /// Not enough funds available to withdraw.
950 NotEnoughFunds,
951 /// Operation not allowed for virtual stakers.
952 VirtualStakerNotAllowed,
953 /// Stash could not be reaped as other pallet might depend on it.
954 CannotReapStash,
955 /// The stake of this account is already migrated to `Fungible` holds.
956 AlreadyMigrated,
957 /// Account is restricted from participation in staking. This may happen if the account is
958 /// staking in another way already, such as via pool.
959 Restricted,
960 }
961
962 #[pallet::hooks]
963 impl<T: Config> Hooks<BlockNumberFor<T>> for Pallet<T> {
964 fn on_initialize(_now: BlockNumberFor<T>) -> Weight {
965 // just return the weight of the on_finalize.
966 T::DbWeight::get().reads(1)
967 }
968
969 fn on_finalize(_n: BlockNumberFor<T>) {
970 // Set the start of the first era.
971 if let Some(mut active_era) = ActiveEra::<T>::get() {
972 if active_era.start.is_none() {
973 let now_as_millis_u64 = T::UnixTime::now().as_millis().saturated_into::<u64>();
974 active_era.start = Some(now_as_millis_u64);
975 // This write only ever happens once, we don't include it in the weight in
976 // general
977 ActiveEra::<T>::put(active_era);
978 }
979 }
980 // `on_finalize` weight is tracked in `on_initialize`
981 }
982
983 fn integrity_test() {
984 // ensure that we funnel the correct value to the `DataProvider::MaxVotesPerVoter`;
985 assert_eq!(
986 MaxNominationsOf::<T>::get(),
987 <Self as ElectionDataProvider>::MaxVotesPerVoter::get()
988 );
989 // and that MaxNominations is always greater than 1, since we count on this.
990 assert!(!MaxNominationsOf::<T>::get().is_zero());
991
992 // ensure election results are always bounded with the same value
993 assert!(
994 <T::ElectionProvider as ElectionProvider>::MaxWinnersPerPage::get() ==
995 <T::GenesisElectionProvider as ElectionProvider>::MaxWinnersPerPage::get()
996 );
997
998 assert!(
999 T::SlashDeferDuration::get() < T::BondingDuration::get() || T::BondingDuration::get() == 0,
1000 "As per documentation, slash defer duration ({}) should be less than bonding duration ({}).",
1001 T::SlashDeferDuration::get(),
1002 T::BondingDuration::get(),
1003 )
1004 }
1005
1006 #[cfg(feature = "try-runtime")]
1007 fn try_state(n: BlockNumberFor<T>) -> Result<(), sp_runtime::TryRuntimeError> {
1008 Self::do_try_state(n)
1009 }
1010 }
1011
1012 impl<T: Config> Pallet<T> {
1013 /// Get the ideal number of active validators.
1014 pub fn validator_count() -> u32 {
1015 ValidatorCount::<T>::get()
1016 }
1017
1018 /// Get the minimum number of staking participants before emergency conditions are imposed.
1019 pub fn minimum_validator_count() -> u32 {
1020 MinimumValidatorCount::<T>::get()
1021 }
1022
1023 /// Get the validators that may never be slashed or forcibly kicked out.
1024 pub fn invulnerables() -> Vec<T::AccountId> {
1025 Invulnerables::<T>::get()
1026 }
1027
1028 /// Get the preferences of a given validator.
1029 pub fn validators<EncodeLikeAccountId>(account_id: EncodeLikeAccountId) -> ValidatorPrefs
1030 where
1031 EncodeLikeAccountId: codec::EncodeLike<T::AccountId>,
1032 {
1033 Validators::<T>::get(account_id)
1034 }
1035
1036 /// Get the nomination preferences of a given nominator.
1037 pub fn nominators<EncodeLikeAccountId>(
1038 account_id: EncodeLikeAccountId,
1039 ) -> Option<Nominations<T>>
1040 where
1041 EncodeLikeAccountId: codec::EncodeLike<T::AccountId>,
1042 {
1043 Nominators::<T>::get(account_id)
1044 }
1045
1046 /// Get the current era index.
1047 pub fn current_era() -> Option<EraIndex> {
1048 CurrentEra::<T>::get()
1049 }
1050
1051 /// Get the active era information.
1052 pub fn active_era() -> Option<ActiveEraInfo> {
1053 ActiveEra::<T>::get()
1054 }
1055
1056 /// Get the session index at which the era starts for the last [`Config::HistoryDepth`]
1057 /// eras.
1058 pub fn eras_start_session_index<EncodeLikeEraIndex>(
1059 era_index: EncodeLikeEraIndex,
1060 ) -> Option<SessionIndex>
1061 where
1062 EncodeLikeEraIndex: codec::EncodeLike<EraIndex>,
1063 {
1064 ErasStartSessionIndex::<T>::get(era_index)
1065 }
1066
1067 /// Get the clipped exposure of a given validator at an era.
1068 pub fn eras_stakers_clipped<EncodeLikeEraIndex, EncodeLikeAccountId>(
1069 era_index: EncodeLikeEraIndex,
1070 account_id: EncodeLikeAccountId,
1071 ) -> Exposure<T::AccountId, BalanceOf<T>>
1072 where
1073 EncodeLikeEraIndex: codec::EncodeLike<EraIndex>,
1074 EncodeLikeAccountId: codec::EncodeLike<T::AccountId>,
1075 {
1076 ErasStakersClipped::<T>::get(era_index, account_id)
1077 }
1078
1079 /// Get the paged history of claimed rewards by era for given validator.
1080 pub fn claimed_rewards<EncodeLikeEraIndex, EncodeLikeAccountId>(
1081 era_index: EncodeLikeEraIndex,
1082 account_id: EncodeLikeAccountId,
1083 ) -> Vec<Page>
1084 where
1085 EncodeLikeEraIndex: codec::EncodeLike<EraIndex>,
1086 EncodeLikeAccountId: codec::EncodeLike<T::AccountId>,
1087 {
1088 ClaimedRewards::<T>::get(era_index, account_id)
1089 }
1090
1091 /// Get the preferences of given validator at given era.
1092 pub fn eras_validator_prefs<EncodeLikeEraIndex, EncodeLikeAccountId>(
1093 era_index: EncodeLikeEraIndex,
1094 account_id: EncodeLikeAccountId,
1095 ) -> ValidatorPrefs
1096 where
1097 EncodeLikeEraIndex: codec::EncodeLike<EraIndex>,
1098 EncodeLikeAccountId: codec::EncodeLike<T::AccountId>,
1099 {
1100 ErasValidatorPrefs::<T>::get(era_index, account_id)
1101 }
1102
1103 /// Get the total validator era payout for the last [`Config::HistoryDepth`] eras.
1104 pub fn eras_validator_reward<EncodeLikeEraIndex>(
1105 era_index: EncodeLikeEraIndex,
1106 ) -> Option<BalanceOf<T>>
1107 where
1108 EncodeLikeEraIndex: codec::EncodeLike<EraIndex>,
1109 {
1110 ErasValidatorReward::<T>::get(era_index)
1111 }
1112
1113 /// Get the rewards for the last [`Config::HistoryDepth`] eras.
1114 pub fn eras_reward_points<EncodeLikeEraIndex>(
1115 era_index: EncodeLikeEraIndex,
1116 ) -> EraRewardPoints<T::AccountId>
1117 where
1118 EncodeLikeEraIndex: codec::EncodeLike<EraIndex>,
1119 {
1120 ErasRewardPoints::<T>::get(era_index)
1121 }
1122
1123 /// Get the total amount staked for the last [`Config::HistoryDepth`] eras.
1124 pub fn eras_total_stake<EncodeLikeEraIndex>(era_index: EncodeLikeEraIndex) -> BalanceOf<T>
1125 where
1126 EncodeLikeEraIndex: codec::EncodeLike<EraIndex>,
1127 {
1128 ErasTotalStake::<T>::get(era_index)
1129 }
1130
1131 /// Get the mode of era forcing.
1132 pub fn force_era() -> Forcing {
1133 ForceEra::<T>::get()
1134 }
1135
1136 /// Get the percentage of the slash that is distributed to reporters.
1137 pub fn slash_reward_fraction() -> Perbill {
1138 SlashRewardFraction::<T>::get()
1139 }
1140
1141 /// Get the amount of canceled slash payout.
1142 pub fn canceled_payout() -> BalanceOf<T> {
1143 CanceledSlashPayout::<T>::get()
1144 }
1145
1146 /// Get the slashing spans for given account.
1147 pub fn slashing_spans<EncodeLikeAccountId>(
1148 account_id: EncodeLikeAccountId,
1149 ) -> Option<slashing::SlashingSpans>
1150 where
1151 EncodeLikeAccountId: codec::EncodeLike<T::AccountId>,
1152 {
1153 SlashingSpans::<T>::get(account_id)
1154 }
1155
1156 /// Get the last planned session scheduled by the session pallet.
1157 pub fn current_planned_session() -> SessionIndex {
1158 CurrentPlannedSession::<T>::get()
1159 }
1160 }
1161
1162 #[pallet::call]
1163 impl<T: Config> Pallet<T> {
1164 /// Take the origin account as a stash and lock up `value` of its balance. `controller` will
1165 /// be the account that controls it.
1166 ///
1167 /// `value` must be more than the `minimum_balance` specified by `T::Currency`.
1168 ///
1169 /// The dispatch origin for this call must be _Signed_ by the stash account.
1170 ///
1171 /// Emits `Bonded`.
1172 /// ## Complexity
1173 /// - Independent of the arguments. Moderate complexity.
1174 /// - O(1).
1175 /// - Three extra DB entries.
1176 ///
1177 /// NOTE: Two of the storage writes (`Self::bonded`, `Self::payee`) are _never_ cleaned
1178 /// unless the `origin` falls below _existential deposit_ (or equal to 0) and gets removed
1179 /// as dust.
1180 #[pallet::call_index(0)]
1181 #[pallet::weight(T::WeightInfo::bond())]
1182 pub fn bond(
1183 origin: OriginFor<T>,
1184 #[pallet::compact] value: BalanceOf<T>,
1185 payee: RewardDestination<T::AccountId>,
1186 ) -> DispatchResult {
1187 let stash = ensure_signed(origin)?;
1188
1189 ensure!(!T::Filter::contains(&stash), Error::<T>::Restricted);
1190
1191 if StakingLedger::<T>::is_bonded(StakingAccount::Stash(stash.clone())) {
1192 return Err(Error::<T>::AlreadyBonded.into())
1193 }
1194
1195 // An existing controller cannot become a stash.
1196 if StakingLedger::<T>::is_bonded(StakingAccount::Controller(stash.clone())) {
1197 return Err(Error::<T>::AlreadyPaired.into())
1198 }
1199
1200 // Reject a bond which is considered to be _dust_.
1201 if value < asset::existential_deposit::<T>() {
1202 return Err(Error::<T>::InsufficientBond.into())
1203 }
1204
1205 let stash_balance = asset::free_to_stake::<T>(&stash);
1206 let value = value.min(stash_balance);
1207 Self::deposit_event(Event::<T>::Bonded { stash: stash.clone(), amount: value });
1208 let ledger = StakingLedger::<T>::new(stash.clone(), value);
1209
1210 // You're auto-bonded forever, here. We might improve this by only bonding when
1211 // you actually validate/nominate and remove once you unbond __everything__.
1212 ledger.bond(payee)?;
1213
1214 Ok(())
1215 }
1216
1217 /// Add some extra amount that have appeared in the stash `free_balance` into the balance up
1218 /// for staking.
1219 ///
1220 /// The dispatch origin for this call must be _Signed_ by the stash, not the controller.
1221 ///
1222 /// Use this if there are additional funds in your stash account that you wish to bond.
1223 /// Unlike [`bond`](Self::bond) or [`unbond`](Self::unbond) this function does not impose
1224 /// any limitation on the amount that can be added.
1225 ///
1226 /// Emits `Bonded`.
1227 ///
1228 /// ## Complexity
1229 /// - Independent of the arguments. Insignificant complexity.
1230 /// - O(1).
1231 #[pallet::call_index(1)]
1232 #[pallet::weight(T::WeightInfo::bond_extra())]
1233 pub fn bond_extra(
1234 origin: OriginFor<T>,
1235 #[pallet::compact] max_additional: BalanceOf<T>,
1236 ) -> DispatchResult {
1237 let stash = ensure_signed(origin)?;
1238 ensure!(!T::Filter::contains(&stash), Error::<T>::Restricted);
1239 Self::do_bond_extra(&stash, max_additional)
1240 }
1241
1242 /// Schedule a portion of the stash to be unlocked ready for transfer out after the bond
1243 /// period ends. If this leaves an amount actively bonded less than
1244 /// [`asset::existential_deposit`], then it is increased to the full amount.
1245 ///
1246 /// The stash may be chilled if the ledger total amount falls to 0 after unbonding.
1247 ///
1248 /// The dispatch origin for this call must be _Signed_ by the controller, not the stash.
1249 ///
1250 /// Once the unlock period is done, you can call `withdraw_unbonded` to actually move
1251 /// the funds out of management ready for transfer.
1252 ///
1253 /// No more than a limited number of unlocking chunks (see `MaxUnlockingChunks`)
1254 /// can co-exists at the same time. If there are no unlocking chunks slots available
1255 /// [`Call::withdraw_unbonded`] is called to remove some of the chunks (if possible).
1256 ///
1257 /// If a user encounters the `InsufficientBond` error when calling this extrinsic,
1258 /// they should call `chill` first in order to free up their bonded funds.
1259 ///
1260 /// Emits `Unbonded`.
1261 ///
1262 /// See also [`Call::withdraw_unbonded`].
1263 #[pallet::call_index(2)]
1264 #[pallet::weight(
1265 T::WeightInfo::withdraw_unbonded_kill(SPECULATIVE_NUM_SPANS).saturating_add(T::WeightInfo::unbond()).saturating_add(T::WeightInfo::chill()))
1266 ]
1267 pub fn unbond(
1268 origin: OriginFor<T>,
1269 #[pallet::compact] value: BalanceOf<T>,
1270 ) -> DispatchResultWithPostInfo {
1271 let controller = ensure_signed(origin)?;
1272
1273 let ledger = Self::ledger(StakingAccount::Controller(controller.clone()))?;
1274
1275 let mut total_weight = if value >= ledger.total {
1276 Self::chill_stash(&ledger.stash);
1277 T::WeightInfo::chill()
1278 } else {
1279 Zero::zero()
1280 };
1281
1282 if let Some(withdraw_weight) = Self::do_unbond(controller, value)? {
1283 total_weight.saturating_accrue(withdraw_weight);
1284 }
1285
1286 Ok(Some(total_weight).into())
1287 }
1288
1289 /// Remove any unlocked chunks from the `unlocking` queue from our management.
1290 ///
1291 /// This essentially frees up that balance to be used by the stash account to do whatever
1292 /// it wants.
1293 ///
1294 /// The dispatch origin for this call must be _Signed_ by the controller.
1295 ///
1296 /// Emits `Withdrawn`.
1297 ///
1298 /// See also [`Call::unbond`].
1299 ///
1300 /// ## Parameters
1301 ///
1302 /// - `num_slashing_spans` indicates the number of metadata slashing spans to clear when
1303 /// this call results in a complete removal of all the data related to the stash account.
1304 /// In this case, the `num_slashing_spans` must be larger or equal to the number of
1305 /// slashing spans associated with the stash account in the [`SlashingSpans`] storage type,
1306 /// otherwise the call will fail. The call weight is directly proportional to
1307 /// `num_slashing_spans`.
1308 ///
1309 /// ## Complexity
1310 /// O(S) where S is the number of slashing spans to remove
1311 /// NOTE: Weight annotation is the kill scenario, we refund otherwise.
1312 #[pallet::call_index(3)]
1313 #[pallet::weight(T::WeightInfo::withdraw_unbonded_kill(*num_slashing_spans))]
1314 pub fn withdraw_unbonded(
1315 origin: OriginFor<T>,
1316 num_slashing_spans: u32,
1317 ) -> DispatchResultWithPostInfo {
1318 let controller = ensure_signed(origin)?;
1319
1320 let actual_weight = Self::do_withdraw_unbonded(&controller, num_slashing_spans)?;
1321 Ok(Some(actual_weight).into())
1322 }
1323
1324 /// Declare the desire to validate for the origin controller.
1325 ///
1326 /// Effects will be felt at the beginning of the next era.
1327 ///
1328 /// The dispatch origin for this call must be _Signed_ by the controller, not the stash.
1329 #[pallet::call_index(4)]
1330 #[pallet::weight(T::WeightInfo::validate())]
1331 pub fn validate(origin: OriginFor<T>, prefs: ValidatorPrefs) -> DispatchResult {
1332 let controller = ensure_signed(origin)?;
1333
1334 let ledger = Self::ledger(Controller(controller))?;
1335
1336 ensure!(ledger.active >= MinValidatorBond::<T>::get(), Error::<T>::InsufficientBond);
1337 let stash = &ledger.stash;
1338
1339 // ensure their commission is correct.
1340 ensure!(prefs.commission >= MinCommission::<T>::get(), Error::<T>::CommissionTooLow);
1341
1342 // Only check limits if they are not already a validator.
1343 if !Validators::<T>::contains_key(stash) {
1344 // If this error is reached, we need to adjust the `MinValidatorBond` and start
1345 // calling `chill_other`. Until then, we explicitly block new validators to protect
1346 // the runtime.
1347 if let Some(max_validators) = MaxValidatorsCount::<T>::get() {
1348 ensure!(
1349 Validators::<T>::count() < max_validators,
1350 Error::<T>::TooManyValidators
1351 );
1352 }
1353 }
1354
1355 Self::do_remove_nominator(stash);
1356 Self::do_add_validator(stash, prefs.clone());
1357 Self::deposit_event(Event::<T>::ValidatorPrefsSet { stash: ledger.stash, prefs });
1358
1359 Ok(())
1360 }
1361
1362 /// Declare the desire to nominate `targets` for the origin controller.
1363 ///
1364 /// Effects will be felt at the beginning of the next era.
1365 ///
1366 /// The dispatch origin for this call must be _Signed_ by the controller, not the stash.
1367 ///
1368 /// ## Complexity
1369 /// - The transaction's complexity is proportional to the size of `targets` (N)
1370 /// which is capped at CompactAssignments::LIMIT (T::MaxNominations).
1371 /// - Both the reads and writes follow a similar pattern.
1372 #[pallet::call_index(5)]
1373 #[pallet::weight(T::WeightInfo::nominate(targets.len() as u32))]
1374 pub fn nominate(
1375 origin: OriginFor<T>,
1376 targets: Vec<AccountIdLookupOf<T>>,
1377 ) -> DispatchResult {
1378 let controller = ensure_signed(origin)?;
1379
1380 let ledger = Self::ledger(StakingAccount::Controller(controller.clone()))?;
1381
1382 ensure!(ledger.active >= MinNominatorBond::<T>::get(), Error::<T>::InsufficientBond);
1383 let stash = &ledger.stash;
1384
1385 // Only check limits if they are not already a nominator.
1386 if !Nominators::<T>::contains_key(stash) {
1387 // If this error is reached, we need to adjust the `MinNominatorBond` and start
1388 // calling `chill_other`. Until then, we explicitly block new nominators to protect
1389 // the runtime.
1390 if let Some(max_nominators) = MaxNominatorsCount::<T>::get() {
1391 ensure!(
1392 Nominators::<T>::count() < max_nominators,
1393 Error::<T>::TooManyNominators
1394 );
1395 }
1396 }
1397
1398 ensure!(!targets.is_empty(), Error::<T>::EmptyTargets);
1399 ensure!(
1400 targets.len() <= T::NominationsQuota::get_quota(ledger.active) as usize,
1401 Error::<T>::TooManyTargets
1402 );
1403
1404 let old = Nominators::<T>::get(stash).map_or_else(Vec::new, |x| x.targets.into_inner());
1405
1406 let targets: BoundedVec<_, _> = targets
1407 .into_iter()
1408 .map(|t| T::Lookup::lookup(t).map_err(DispatchError::from))
1409 .map(|n| {
1410 n.and_then(|n| {
1411 if old.contains(&n) || !Validators::<T>::get(&n).blocked {
1412 Ok(n)
1413 } else {
1414 Err(Error::<T>::BadTarget.into())
1415 }
1416 })
1417 })
1418 .collect::<Result<Vec<_>, _>>()?
1419 .try_into()
1420 .map_err(|_| Error::<T>::TooManyNominators)?;
1421
1422 let nominations = Nominations {
1423 targets,
1424 // Initial nominations are considered submitted at era 0. See `Nominations` doc.
1425 submitted_in: CurrentEra::<T>::get().unwrap_or(0),
1426 suppressed: false,
1427 };
1428
1429 Self::do_remove_validator(stash);
1430 Self::do_add_nominator(stash, nominations);
1431 Ok(())
1432 }
1433
1434 /// Declare no desire to either validate or nominate.
1435 ///
1436 /// Effects will be felt at the beginning of the next era.
1437 ///
1438 /// The dispatch origin for this call must be _Signed_ by the controller, not the stash.
1439 ///
1440 /// ## Complexity
1441 /// - Independent of the arguments. Insignificant complexity.
1442 /// - Contains one read.
1443 /// - Writes are limited to the `origin` account key.
1444 #[pallet::call_index(6)]
1445 #[pallet::weight(T::WeightInfo::chill())]
1446 pub fn chill(origin: OriginFor<T>) -> DispatchResult {
1447 let controller = ensure_signed(origin)?;
1448
1449 let ledger = Self::ledger(StakingAccount::Controller(controller))?;
1450
1451 Self::chill_stash(&ledger.stash);
1452 Ok(())
1453 }
1454
1455 /// (Re-)set the payment target for a controller.
1456 ///
1457 /// Effects will be felt instantly (as soon as this function is completed successfully).
1458 ///
1459 /// The dispatch origin for this call must be _Signed_ by the controller, not the stash.
1460 ///
1461 /// ## Complexity
1462 /// - O(1)
1463 /// - Independent of the arguments. Insignificant complexity.
1464 /// - Contains a limited number of reads.
1465 /// - Writes are limited to the `origin` account key.
1466 /// ---------
1467 #[pallet::call_index(7)]
1468 #[pallet::weight(T::WeightInfo::set_payee())]
1469 pub fn set_payee(
1470 origin: OriginFor<T>,
1471 payee: RewardDestination<T::AccountId>,
1472 ) -> DispatchResult {
1473 let controller = ensure_signed(origin)?;
1474 let ledger = Self::ledger(Controller(controller.clone()))?;
1475
1476 ensure!(
1477 (payee != {
1478 #[allow(deprecated)]
1479 RewardDestination::Controller
1480 }),
1481 Error::<T>::ControllerDeprecated
1482 );
1483
1484 ledger
1485 .set_payee(payee)
1486 .defensive_proof("ledger was retrieved from storage, thus it's bonded; qed.")?;
1487
1488 Ok(())
1489 }
1490
1491 /// (Re-)sets the controller of a stash to the stash itself. This function previously
1492 /// accepted a `controller` argument to set the controller to an account other than the
1493 /// stash itself. This functionality has now been removed, now only setting the controller
1494 /// to the stash, if it is not already.
1495 ///
1496 /// Effects will be felt instantly (as soon as this function is completed successfully).
1497 ///
1498 /// The dispatch origin for this call must be _Signed_ by the stash, not the controller.
1499 ///
1500 /// ## Complexity
1501 /// O(1)
1502 /// - Independent of the arguments. Insignificant complexity.
1503 /// - Contains a limited number of reads.
1504 /// - Writes are limited to the `origin` account key.
1505 #[pallet::call_index(8)]
1506 #[pallet::weight(T::WeightInfo::set_controller())]
1507 pub fn set_controller(origin: OriginFor<T>) -> DispatchResult {
1508 let stash = ensure_signed(origin)?;
1509
1510 Self::ledger(StakingAccount::Stash(stash.clone())).map(|ledger| {
1511 let controller = ledger.controller()
1512 .defensive_proof("Ledger's controller field didn't exist. The controller should have been fetched using StakingLedger.")
1513 .ok_or(Error::<T>::NotController)?;
1514
1515 if controller == stash {
1516 // Stash is already its own controller.
1517 return Err(Error::<T>::AlreadyPaired.into())
1518 }
1519
1520 ledger.set_controller_to_stash()?;
1521 Ok(())
1522 })?
1523 }
1524
1525 /// Sets the ideal number of validators.
1526 ///
1527 /// The dispatch origin must be Root.
1528 ///
1529 /// ## Complexity
1530 /// O(1)
1531 #[pallet::call_index(9)]
1532 #[pallet::weight(T::WeightInfo::set_validator_count())]
1533 pub fn set_validator_count(
1534 origin: OriginFor<T>,
1535 #[pallet::compact] new: u32,
1536 ) -> DispatchResult {
1537 ensure_root(origin)?;
1538 // ensure new validator count does not exceed maximum winners
1539 // support by election provider.
1540 ensure!(new <= T::MaxValidatorSet::get(), Error::<T>::TooManyValidators);
1541
1542 ValidatorCount::<T>::put(new);
1543 Ok(())
1544 }
1545
1546 /// Increments the ideal number of validators up to maximum of
1547 /// `ElectionProviderBase::MaxWinners`.
1548 ///
1549 /// The dispatch origin must be Root.
1550 ///
1551 /// ## Complexity
1552 /// Same as [`Self::set_validator_count`].
1553 #[pallet::call_index(10)]
1554 #[pallet::weight(T::WeightInfo::set_validator_count())]
1555 pub fn increase_validator_count(
1556 origin: OriginFor<T>,
1557 #[pallet::compact] additional: u32,
1558 ) -> DispatchResult {
1559 ensure_root(origin)?;
1560 let old = ValidatorCount::<T>::get();
1561 let new = old.checked_add(additional).ok_or(ArithmeticError::Overflow)?;
1562 ensure!(new <= T::MaxValidatorSet::get(), Error::<T>::TooManyValidators);
1563
1564 ValidatorCount::<T>::put(new);
1565 Ok(())
1566 }
1567
1568 /// Scale up the ideal number of validators by a factor up to maximum of
1569 /// `ElectionProviderBase::MaxWinners`.
1570 ///
1571 /// The dispatch origin must be Root.
1572 ///
1573 /// ## Complexity
1574 /// Same as [`Self::set_validator_count`].
1575 #[pallet::call_index(11)]
1576 #[pallet::weight(T::WeightInfo::set_validator_count())]
1577 pub fn scale_validator_count(origin: OriginFor<T>, factor: Percent) -> DispatchResult {
1578 ensure_root(origin)?;
1579 let old = ValidatorCount::<T>::get();
1580 let new = old.checked_add(factor.mul_floor(old)).ok_or(ArithmeticError::Overflow)?;
1581
1582 ensure!(new <= T::MaxValidatorSet::get(), Error::<T>::TooManyValidators);
1583
1584 ValidatorCount::<T>::put(new);
1585 Ok(())
1586 }
1587
1588 /// Force there to be no new eras indefinitely.
1589 ///
1590 /// The dispatch origin must be Root.
1591 ///
1592 /// # Warning
1593 ///
1594 /// The election process starts multiple blocks before the end of the era.
1595 /// Thus the election process may be ongoing when this is called. In this case the
1596 /// election will continue until the next era is triggered.
1597 ///
1598 /// ## Complexity
1599 /// - No arguments.
1600 /// - Weight: O(1)
1601 #[pallet::call_index(12)]
1602 #[pallet::weight(T::WeightInfo::force_no_eras())]
1603 pub fn force_no_eras(origin: OriginFor<T>) -> DispatchResult {
1604 ensure_root(origin)?;
1605 Self::set_force_era(Forcing::ForceNone);
1606 Ok(())
1607 }
1608
1609 /// Force there to be a new era at the end of the next session. After this, it will be
1610 /// reset to normal (non-forced) behaviour.
1611 ///
1612 /// The dispatch origin must be Root.
1613 ///
1614 /// # Warning
1615 ///
1616 /// The election process starts multiple blocks before the end of the era.
1617 /// If this is called just before a new era is triggered, the election process may not
1618 /// have enough blocks to get a result.
1619 ///
1620 /// ## Complexity
1621 /// - No arguments.
1622 /// - Weight: O(1)
1623 #[pallet::call_index(13)]
1624 #[pallet::weight(T::WeightInfo::force_new_era())]
1625 pub fn force_new_era(origin: OriginFor<T>) -> DispatchResult {
1626 ensure_root(origin)?;
1627 Self::set_force_era(Forcing::ForceNew);
1628 Ok(())
1629 }
1630
1631 /// Set the validators who cannot be slashed (if any).
1632 ///
1633 /// The dispatch origin must be Root.
1634 #[pallet::call_index(14)]
1635 #[pallet::weight(T::WeightInfo::set_invulnerables(invulnerables.len() as u32))]
1636 pub fn set_invulnerables(
1637 origin: OriginFor<T>,
1638 invulnerables: Vec<T::AccountId>,
1639 ) -> DispatchResult {
1640 ensure_root(origin)?;
1641 <Invulnerables<T>>::put(invulnerables);
1642 Ok(())
1643 }
1644
1645 /// Force a current staker to become completely unstaked, immediately.
1646 ///
1647 /// The dispatch origin must be Root.
1648 ///
1649 /// ## Parameters
1650 ///
1651 /// - `num_slashing_spans`: Refer to comments on [`Call::withdraw_unbonded`] for more
1652 /// details.
1653 #[pallet::call_index(15)]
1654 #[pallet::weight(T::WeightInfo::force_unstake(*num_slashing_spans))]
1655 pub fn force_unstake(
1656 origin: OriginFor<T>,
1657 stash: T::AccountId,
1658 num_slashing_spans: u32,
1659 ) -> DispatchResult {
1660 ensure_root(origin)?;
1661
1662 // Remove all staking-related information and lock.
1663 Self::kill_stash(&stash, num_slashing_spans)?;
1664
1665 Ok(())
1666 }
1667
1668 /// Force there to be a new era at the end of sessions indefinitely.
1669 ///
1670 /// The dispatch origin must be Root.
1671 ///
1672 /// # Warning
1673 ///
1674 /// The election process starts multiple blocks before the end of the era.
1675 /// If this is called just before a new era is triggered, the election process may not
1676 /// have enough blocks to get a result.
1677 #[pallet::call_index(16)]
1678 #[pallet::weight(T::WeightInfo::force_new_era_always())]
1679 pub fn force_new_era_always(origin: OriginFor<T>) -> DispatchResult {
1680 ensure_root(origin)?;
1681 Self::set_force_era(Forcing::ForceAlways);
1682 Ok(())
1683 }
1684
1685 /// Cancel enactment of a deferred slash.
1686 ///
1687 /// Can be called by the `T::AdminOrigin`.
1688 ///
1689 /// Parameters: era and indices of the slashes for that era to kill.
1690 /// They **must** be sorted in ascending order, *and* unique.
1691 #[pallet::call_index(17)]
1692 #[pallet::weight(T::WeightInfo::cancel_deferred_slash(slash_indices.len() as u32))]
1693 pub fn cancel_deferred_slash(
1694 origin: OriginFor<T>,
1695 era: EraIndex,
1696 slash_indices: Vec<u32>,
1697 ) -> DispatchResult {
1698 T::AdminOrigin::ensure_origin(origin)?;
1699
1700 ensure!(!slash_indices.is_empty(), Error::<T>::EmptyTargets);
1701 ensure!(is_sorted_and_unique(&slash_indices), Error::<T>::NotSortedAndUnique);
1702
1703 let mut unapplied = UnappliedSlashes::<T>::get(&era);
1704 let last_item = slash_indices[slash_indices.len() - 1];
1705 ensure!((last_item as usize) < unapplied.len(), Error::<T>::InvalidSlashIndex);
1706
1707 for (removed, index) in slash_indices.into_iter().enumerate() {
1708 let index = (index as usize) - removed;
1709 unapplied.remove(index);
1710 }
1711
1712 UnappliedSlashes::<T>::insert(&era, &unapplied);
1713 Ok(())
1714 }
1715
1716 /// Pay out next page of the stakers behind a validator for the given era.
1717 ///
1718 /// - `validator_stash` is the stash account of the validator.
1719 /// - `era` may be any era between `[current_era - history_depth; current_era]`.
1720 ///
1721 /// The origin of this call must be _Signed_. Any account can call this function, even if
1722 /// it is not one of the stakers.
1723 ///
1724 /// The reward payout could be paged in case there are too many nominators backing the
1725 /// `validator_stash`. This call will payout unpaid pages in an ascending order. To claim a
1726 /// specific page, use `payout_stakers_by_page`.`
1727 ///
1728 /// If all pages are claimed, it returns an error `InvalidPage`.
1729 #[pallet::call_index(18)]
1730 #[pallet::weight(T::WeightInfo::payout_stakers_alive_staked(T::MaxExposurePageSize::get()))]
1731 pub fn payout_stakers(
1732 origin: OriginFor<T>,
1733 validator_stash: T::AccountId,
1734 era: EraIndex,
1735 ) -> DispatchResultWithPostInfo {
1736 ensure_signed(origin)?;
1737 Self::do_payout_stakers(validator_stash, era)
1738 }
1739
1740 /// Rebond a portion of the stash scheduled to be unlocked.
1741 ///
1742 /// The dispatch origin must be signed by the controller.
1743 ///
1744 /// ## Complexity
1745 /// - Time complexity: O(L), where L is unlocking chunks
1746 /// - Bounded by `MaxUnlockingChunks`.
1747 #[pallet::call_index(19)]
1748 #[pallet::weight(T::WeightInfo::rebond(T::MaxUnlockingChunks::get() as u32))]
1749 pub fn rebond(
1750 origin: OriginFor<T>,
1751 #[pallet::compact] value: BalanceOf<T>,
1752 ) -> DispatchResultWithPostInfo {
1753 let controller = ensure_signed(origin)?;
1754 let ledger = Self::ledger(Controller(controller))?;
1755
1756 ensure!(!T::Filter::contains(&ledger.stash), Error::<T>::Restricted);
1757 ensure!(!ledger.unlocking.is_empty(), Error::<T>::NoUnlockChunk);
1758
1759 let initial_unlocking = ledger.unlocking.len() as u32;
1760 let (ledger, rebonded_value) = ledger.rebond(value);
1761 // Last check: the new active amount of ledger must be more than ED.
1762 ensure!(
1763 ledger.active >= asset::existential_deposit::<T>(),
1764 Error::<T>::InsufficientBond
1765 );
1766
1767 Self::deposit_event(Event::<T>::Bonded {
1768 stash: ledger.stash.clone(),
1769 amount: rebonded_value,
1770 });
1771
1772 let stash = ledger.stash.clone();
1773 let final_unlocking = ledger.unlocking.len();
1774
1775 // NOTE: ledger must be updated prior to calling `Self::weight_of`.
1776 ledger.update()?;
1777 if T::VoterList::contains(&stash) {
1778 let _ = T::VoterList::on_update(&stash, Self::weight_of(&stash)).defensive();
1779 }
1780
1781 let removed_chunks = 1u32 // for the case where the last iterated chunk is not removed
1782 .saturating_add(initial_unlocking)
1783 .saturating_sub(final_unlocking as u32);
1784 Ok(Some(T::WeightInfo::rebond(removed_chunks)).into())
1785 }
1786
1787 /// Remove all data structures concerning a staker/stash once it is at a state where it can
1788 /// be considered `dust` in the staking system. The requirements are:
1789 ///
1790 /// 1. the `total_balance` of the stash is below existential deposit.
1791 /// 2. or, the `ledger.total` of the stash is below existential deposit.
1792 /// 3. or, existential deposit is zero and either `total_balance` or `ledger.total` is zero.
1793 ///
1794 /// The former can happen in cases like a slash; the latter when a fully unbonded account
1795 /// is still receiving staking rewards in `RewardDestination::Staked`.
1796 ///
1797 /// It can be called by anyone, as long as `stash` meets the above requirements.
1798 ///
1799 /// Refunds the transaction fees upon successful execution.
1800 ///
1801 /// ## Parameters
1802 ///
1803 /// - `num_slashing_spans`: Refer to comments on [`Call::withdraw_unbonded`] for more
1804 /// details.
1805 #[pallet::call_index(20)]
1806 #[pallet::weight(T::WeightInfo::reap_stash(*num_slashing_spans))]
1807 pub fn reap_stash(
1808 origin: OriginFor<T>,
1809 stash: T::AccountId,
1810 num_slashing_spans: u32,
1811 ) -> DispatchResultWithPostInfo {
1812 ensure_signed(origin)?;
1813
1814 // virtual stakers should not be allowed to be reaped.
1815 ensure!(!Self::is_virtual_staker(&stash), Error::<T>::VirtualStakerNotAllowed);
1816
1817 let ed = asset::existential_deposit::<T>();
1818 let origin_balance = asset::total_balance::<T>(&stash);
1819 let ledger_total =
1820 Self::ledger(Stash(stash.clone())).map(|l| l.total).unwrap_or_default();
1821 let reapable = origin_balance < ed ||
1822 origin_balance.is_zero() ||
1823 ledger_total < ed ||
1824 ledger_total.is_zero();
1825 ensure!(reapable, Error::<T>::FundedTarget);
1826
1827 // Remove all staking-related information and lock.
1828 Self::kill_stash(&stash, num_slashing_spans)?;
1829
1830 Ok(Pays::No.into())
1831 }
1832
1833 /// Remove the given nominations from the calling validator.
1834 ///
1835 /// Effects will be felt at the beginning of the next era.
1836 ///
1837 /// The dispatch origin for this call must be _Signed_ by the controller, not the stash.
1838 ///
1839 /// - `who`: A list of nominator stash accounts who are nominating this validator which
1840 /// should no longer be nominating this validator.
1841 ///
1842 /// Note: Making this call only makes sense if you first set the validator preferences to
1843 /// block any further nominations.
1844 #[pallet::call_index(21)]
1845 #[pallet::weight(T::WeightInfo::kick(who.len() as u32))]
1846 pub fn kick(origin: OriginFor<T>, who: Vec<AccountIdLookupOf<T>>) -> DispatchResult {
1847 let controller = ensure_signed(origin)?;
1848 let ledger = Self::ledger(Controller(controller))?;
1849 let stash = &ledger.stash;
1850
1851 for nom_stash in who
1852 .into_iter()
1853 .map(T::Lookup::lookup)
1854 .collect::<Result<Vec<T::AccountId>, _>>()?
1855 .into_iter()
1856 {
1857 Nominators::<T>::mutate(&nom_stash, |maybe_nom| {
1858 if let Some(ref mut nom) = maybe_nom {
1859 if let Some(pos) = nom.targets.iter().position(|v| v == stash) {
1860 nom.targets.swap_remove(pos);
1861 Self::deposit_event(Event::<T>::Kicked {
1862 nominator: nom_stash.clone(),
1863 stash: stash.clone(),
1864 });
1865 }
1866 }
1867 });
1868 }
1869
1870 Ok(())
1871 }
1872
1873 /// Update the various staking configurations .
1874 ///
1875 /// * `min_nominator_bond`: The minimum active bond needed to be a nominator.
1876 /// * `min_validator_bond`: The minimum active bond needed to be a validator.
1877 /// * `max_nominator_count`: The max number of users who can be a nominator at once. When
1878 /// set to `None`, no limit is enforced.
1879 /// * `max_validator_count`: The max number of users who can be a validator at once. When
1880 /// set to `None`, no limit is enforced.
1881 /// * `chill_threshold`: The ratio of `max_nominator_count` or `max_validator_count` which
1882 /// should be filled in order for the `chill_other` transaction to work.
1883 /// * `min_commission`: The minimum amount of commission that each validators must maintain.
1884 /// This is checked only upon calling `validate`. Existing validators are not affected.
1885 ///
1886 /// RuntimeOrigin must be Root to call this function.
1887 ///
1888 /// NOTE: Existing nominators and validators will not be affected by this update.
1889 /// to kick people under the new limits, `chill_other` should be called.
1890 // We assume the worst case for this call is either: all items are set or all items are
1891 // removed.
1892 #[pallet::call_index(22)]
1893 #[pallet::weight(
1894 T::WeightInfo::set_staking_configs_all_set()
1895 .max(T::WeightInfo::set_staking_configs_all_remove())
1896 )]
1897 pub fn set_staking_configs(
1898 origin: OriginFor<T>,
1899 min_nominator_bond: ConfigOp<BalanceOf<T>>,
1900 min_validator_bond: ConfigOp<BalanceOf<T>>,
1901 max_nominator_count: ConfigOp<u32>,
1902 max_validator_count: ConfigOp<u32>,
1903 chill_threshold: ConfigOp<Percent>,
1904 min_commission: ConfigOp<Perbill>,
1905 max_staked_rewards: ConfigOp<Percent>,
1906 ) -> DispatchResult {
1907 ensure_root(origin)?;
1908
1909 macro_rules! config_op_exp {
1910 ($storage:ty, $op:ident) => {
1911 match $op {
1912 ConfigOp::Noop => (),
1913 ConfigOp::Set(v) => <$storage>::put(v),
1914 ConfigOp::Remove => <$storage>::kill(),
1915 }
1916 };
1917 }
1918
1919 config_op_exp!(MinNominatorBond<T>, min_nominator_bond);
1920 config_op_exp!(MinValidatorBond<T>, min_validator_bond);
1921 config_op_exp!(MaxNominatorsCount<T>, max_nominator_count);
1922 config_op_exp!(MaxValidatorsCount<T>, max_validator_count);
1923 config_op_exp!(ChillThreshold<T>, chill_threshold);
1924 config_op_exp!(MinCommission<T>, min_commission);
1925 config_op_exp!(MaxStakedRewards<T>, max_staked_rewards);
1926 Ok(())
1927 }
1928 /// Declare a `controller` to stop participating as either a validator or nominator.
1929 ///
1930 /// Effects will be felt at the beginning of the next era.
1931 ///
1932 /// The dispatch origin for this call must be _Signed_, but can be called by anyone.
1933 ///
1934 /// If the caller is the same as the controller being targeted, then no further checks are
1935 /// enforced, and this function behaves just like `chill`.
1936 ///
1937 /// If the caller is different than the controller being targeted, the following conditions
1938 /// must be met:
1939 ///
1940 /// * `controller` must belong to a nominator who has become non-decodable,
1941 ///
1942 /// Or:
1943 ///
1944 /// * A `ChillThreshold` must be set and checked which defines how close to the max
1945 /// nominators or validators we must reach before users can start chilling one-another.
1946 /// * A `MaxNominatorCount` and `MaxValidatorCount` must be set which is used to determine
1947 /// how close we are to the threshold.
1948 /// * A `MinNominatorBond` and `MinValidatorBond` must be set and checked, which determines
1949 /// if this is a person that should be chilled because they have not met the threshold
1950 /// bond required.
1951 ///
1952 /// This can be helpful if bond requirements are updated, and we need to remove old users
1953 /// who do not satisfy these requirements.
1954 #[pallet::call_index(23)]
1955 #[pallet::weight(T::WeightInfo::chill_other())]
1956 pub fn chill_other(origin: OriginFor<T>, stash: T::AccountId) -> DispatchResult {
1957 // Anyone can call this function.
1958 let caller = ensure_signed(origin)?;
1959 let ledger = Self::ledger(Stash(stash.clone()))?;
1960 let controller = ledger
1961 .controller()
1962 .defensive_proof(
1963 "Ledger's controller field didn't exist. The controller should have been fetched using StakingLedger.",
1964 )
1965 .ok_or(Error::<T>::NotController)?;
1966
1967 // In order for one user to chill another user, the following conditions must be met:
1968 //
1969 // * `controller` belongs to a nominator who has become non-decodable,
1970 //
1971 // Or
1972 //
1973 // * A `ChillThreshold` is set which defines how close to the max nominators or
1974 // validators we must reach before users can start chilling one-another.
1975 // * A `MaxNominatorCount` and `MaxValidatorCount` which is used to determine how close
1976 // we are to the threshold.
1977 // * A `MinNominatorBond` and `MinValidatorBond` which is the final condition checked to
1978 // determine this is a person that should be chilled because they have not met the
1979 // threshold bond required.
1980 //
1981 // Otherwise, if caller is the same as the controller, this is just like `chill`.
1982
1983 if Nominators::<T>::contains_key(&stash) && Nominators::<T>::get(&stash).is_none() {
1984 Self::chill_stash(&stash);
1985 return Ok(())
1986 }
1987
1988 if caller != controller {
1989 let threshold = ChillThreshold::<T>::get().ok_or(Error::<T>::CannotChillOther)?;
1990 let min_active_bond = if Nominators::<T>::contains_key(&stash) {
1991 let max_nominator_count =
1992 MaxNominatorsCount::<T>::get().ok_or(Error::<T>::CannotChillOther)?;
1993 let current_nominator_count = Nominators::<T>::count();
1994 ensure!(
1995 threshold * max_nominator_count < current_nominator_count,
1996 Error::<T>::CannotChillOther
1997 );
1998 MinNominatorBond::<T>::get()
1999 } else if Validators::<T>::contains_key(&stash) {
2000 let max_validator_count =
2001 MaxValidatorsCount::<T>::get().ok_or(Error::<T>::CannotChillOther)?;
2002 let current_validator_count = Validators::<T>::count();
2003 ensure!(
2004 threshold * max_validator_count < current_validator_count,
2005 Error::<T>::CannotChillOther
2006 );
2007 MinValidatorBond::<T>::get()
2008 } else {
2009 Zero::zero()
2010 };
2011
2012 ensure!(ledger.active < min_active_bond, Error::<T>::CannotChillOther);
2013 }
2014
2015 Self::chill_stash(&stash);
2016 Ok(())
2017 }
2018
2019 /// Force a validator to have at least the minimum commission. This will not affect a
2020 /// validator who already has a commission greater than or equal to the minimum. Any account
2021 /// can call this.
2022 #[pallet::call_index(24)]
2023 #[pallet::weight(T::WeightInfo::force_apply_min_commission())]
2024 pub fn force_apply_min_commission(
2025 origin: OriginFor<T>,
2026 validator_stash: T::AccountId,
2027 ) -> DispatchResult {
2028 ensure_signed(origin)?;
2029 let min_commission = MinCommission::<T>::get();
2030 Validators::<T>::try_mutate_exists(validator_stash, |maybe_prefs| {
2031 maybe_prefs
2032 .as_mut()
2033 .map(|prefs| {
2034 (prefs.commission < min_commission)
2035 .then(|| prefs.commission = min_commission)
2036 })
2037 .ok_or(Error::<T>::NotStash)
2038 })?;
2039 Ok(())
2040 }
2041
2042 /// Sets the minimum amount of commission that each validators must maintain.
2043 ///
2044 /// This call has lower privilege requirements than `set_staking_config` and can be called
2045 /// by the `T::AdminOrigin`. Root can always call this.
2046 #[pallet::call_index(25)]
2047 #[pallet::weight(T::WeightInfo::set_min_commission())]
2048 pub fn set_min_commission(origin: OriginFor<T>, new: Perbill) -> DispatchResult {
2049 T::AdminOrigin::ensure_origin(origin)?;
2050 MinCommission::<T>::put(new);
2051 Ok(())
2052 }
2053
2054 /// Pay out a page of the stakers behind a validator for the given era and page.
2055 ///
2056 /// - `validator_stash` is the stash account of the validator.
2057 /// - `era` may be any era between `[current_era - history_depth; current_era]`.
2058 /// - `page` is the page index of nominators to pay out with value between 0 and
2059 /// `num_nominators / T::MaxExposurePageSize`.
2060 ///
2061 /// The origin of this call must be _Signed_. Any account can call this function, even if
2062 /// it is not one of the stakers.
2063 ///
2064 /// If a validator has more than [`Config::MaxExposurePageSize`] nominators backing
2065 /// them, then the list of nominators is paged, with each page being capped at
2066 /// [`Config::MaxExposurePageSize`.] If a validator has more than one page of nominators,
2067 /// the call needs to be made for each page separately in order for all the nominators
2068 /// backing a validator to receive the reward. The nominators are not sorted across pages
2069 /// and so it should not be assumed the highest staker would be on the topmost page and vice
2070 /// versa. If rewards are not claimed in [`Config::HistoryDepth`] eras, they are lost.
2071 #[pallet::call_index(26)]
2072 #[pallet::weight(T::WeightInfo::payout_stakers_alive_staked(T::MaxExposurePageSize::get()))]
2073 pub fn payout_stakers_by_page(
2074 origin: OriginFor<T>,
2075 validator_stash: T::AccountId,
2076 era: EraIndex,
2077 page: Page,
2078 ) -> DispatchResultWithPostInfo {
2079 ensure_signed(origin)?;
2080 Self::do_payout_stakers_by_page(validator_stash, era, page)
2081 }
2082
2083 /// Migrates an account's `RewardDestination::Controller` to
2084 /// `RewardDestination::Account(controller)`.
2085 ///
2086 /// Effects will be felt instantly (as soon as this function is completed successfully).
2087 ///
2088 /// This will waive the transaction fee if the `payee` is successfully migrated.
2089 #[pallet::call_index(27)]
2090 #[pallet::weight(T::WeightInfo::update_payee())]
2091 pub fn update_payee(
2092 origin: OriginFor<T>,
2093 controller: T::AccountId,
2094 ) -> DispatchResultWithPostInfo {
2095 ensure_signed(origin)?;
2096 let ledger = Self::ledger(StakingAccount::Controller(controller.clone()))?;
2097
2098 ensure!(
2099 (Payee::<T>::get(&ledger.stash) == {
2100 #[allow(deprecated)]
2101 Some(RewardDestination::Controller)
2102 }),
2103 Error::<T>::NotController
2104 );
2105
2106 ledger
2107 .set_payee(RewardDestination::Account(controller))
2108 .defensive_proof("ledger should have been previously retrieved from storage.")?;
2109
2110 Ok(Pays::No.into())
2111 }
2112
2113 /// Updates a batch of controller accounts to their corresponding stash account if they are
2114 /// not the same. Ignores any controller accounts that do not exist, and does not operate if
2115 /// the stash and controller are already the same.
2116 ///
2117 /// Effects will be felt instantly (as soon as this function is completed successfully).
2118 ///
2119 /// The dispatch origin must be `T::AdminOrigin`.
2120 #[pallet::call_index(28)]
2121 #[pallet::weight(T::WeightInfo::deprecate_controller_batch(controllers.len() as u32))]
2122 pub fn deprecate_controller_batch(
2123 origin: OriginFor<T>,
2124 controllers: BoundedVec<T::AccountId, T::MaxControllersInDeprecationBatch>,
2125 ) -> DispatchResultWithPostInfo {
2126 T::AdminOrigin::ensure_origin(origin)?;
2127
2128 // Ignore controllers that do not exist or are already the same as stash.
2129 let filtered_batch_with_ledger: Vec<_> = controllers
2130 .iter()
2131 .filter_map(|controller| {
2132 let ledger = Self::ledger(StakingAccount::Controller(controller.clone()));
2133 ledger.ok().map_or(None, |ledger| {
2134 // If the controller `RewardDestination` is still the deprecated
2135 // `Controller` variant, skip deprecating this account.
2136 let payee_deprecated = Payee::<T>::get(&ledger.stash) == {
2137 #[allow(deprecated)]
2138 Some(RewardDestination::Controller)
2139 };
2140
2141 if ledger.stash != *controller && !payee_deprecated {
2142 Some(ledger)
2143 } else {
2144 None
2145 }
2146 })
2147 })
2148 .collect();
2149
2150 // Update unique pairs.
2151 let mut failures = 0;
2152 for ledger in filtered_batch_with_ledger {
2153 let _ = ledger.clone().set_controller_to_stash().map_err(|_| failures += 1);
2154 }
2155 Self::deposit_event(Event::<T>::ControllerBatchDeprecated { failures });
2156
2157 Ok(Some(T::WeightInfo::deprecate_controller_batch(controllers.len() as u32)).into())
2158 }
2159
2160 /// Restores the state of a ledger which is in an inconsistent state.
2161 ///
2162 /// The requirements to restore a ledger are the following:
2163 /// * The stash is bonded; or
2164 /// * The stash is not bonded but it has a staking lock left behind; or
2165 /// * If the stash has an associated ledger and its state is inconsistent; or
2166 /// * If the ledger is not corrupted *but* its staking lock is out of sync.
2167 ///
2168 /// The `maybe_*` input parameters will overwrite the corresponding data and metadata of the
2169 /// ledger associated with the stash. If the input parameters are not set, the ledger will
2170 /// be reset values from on-chain state.
2171 #[pallet::call_index(29)]
2172 #[pallet::weight(T::WeightInfo::restore_ledger())]
2173 pub fn restore_ledger(
2174 origin: OriginFor<T>,
2175 stash: T::AccountId,
2176 maybe_controller: Option<T::AccountId>,
2177 maybe_total: Option<BalanceOf<T>>,
2178 maybe_unlocking: Option<BoundedVec<UnlockChunk<BalanceOf<T>>, T::MaxUnlockingChunks>>,
2179 ) -> DispatchResult {
2180 T::AdminOrigin::ensure_origin(origin)?;
2181
2182 // cannot restore ledger for virtual stakers.
2183 ensure!(!Self::is_virtual_staker(&stash), Error::<T>::VirtualStakerNotAllowed);
2184
2185 let current_lock = asset::staked::<T>(&stash);
2186 let stash_balance = asset::stakeable_balance::<T>(&stash);
2187
2188 let (new_controller, new_total) = match Self::inspect_bond_state(&stash) {
2189 Ok(LedgerIntegrityState::Corrupted) => {
2190 let new_controller = maybe_controller.unwrap_or(stash.clone());
2191
2192 let new_total = if let Some(total) = maybe_total {
2193 let new_total = total.min(stash_balance);
2194 // enforce hold == ledger.amount.
2195 asset::update_stake::<T>(&stash, new_total)?;
2196 new_total
2197 } else {
2198 current_lock
2199 };
2200
2201 Ok((new_controller, new_total))
2202 },
2203 Ok(LedgerIntegrityState::CorruptedKilled) => {
2204 if current_lock == Zero::zero() {
2205 // this case needs to restore both lock and ledger, so the new total needs
2206 // to be given by the called since there's no way to restore the total
2207 // on-chain.
2208 ensure!(maybe_total.is_some(), Error::<T>::CannotRestoreLedger);
2209 Ok((
2210 stash.clone(),
2211 maybe_total.expect("total exists as per the check above; qed."),
2212 ))
2213 } else {
2214 Ok((stash.clone(), current_lock))
2215 }
2216 },
2217 Ok(LedgerIntegrityState::LockCorrupted) => {
2218 // ledger is not corrupted but its locks are out of sync. In this case, we need
2219 // to enforce a new ledger.total and staking lock for this stash.
2220 let new_total =
2221 maybe_total.ok_or(Error::<T>::CannotRestoreLedger)?.min(stash_balance);
2222 asset::update_stake::<T>(&stash, new_total)?;
2223
2224 Ok((stash.clone(), new_total))
2225 },
2226 Err(Error::<T>::BadState) => {
2227 // the stash and ledger do not exist but lock is lingering.
2228 asset::kill_stake::<T>(&stash)?;
2229 ensure!(
2230 Self::inspect_bond_state(&stash) == Err(Error::<T>::NotStash),
2231 Error::<T>::BadState
2232 );
2233
2234 return Ok(());
2235 },
2236 Ok(LedgerIntegrityState::Ok) | Err(_) => Err(Error::<T>::CannotRestoreLedger),
2237 }?;
2238
2239 // re-bond stash and controller tuple.
2240 Bonded::<T>::insert(&stash, &new_controller);
2241
2242 // resoter ledger state.
2243 let mut ledger = StakingLedger::<T>::new(stash.clone(), new_total);
2244 ledger.controller = Some(new_controller);
2245 ledger.unlocking = maybe_unlocking.unwrap_or_default();
2246 ledger.update()?;
2247
2248 ensure!(
2249 Self::inspect_bond_state(&stash) == Ok(LedgerIntegrityState::Ok),
2250 Error::<T>::BadState
2251 );
2252 Ok(())
2253 }
2254
2255 /// Removes the legacy Staking locks if they exist.
2256 ///
2257 /// This removes the legacy lock on the stake with [`Config::OldCurrency`] and creates a
2258 /// hold on it if needed. If all stake cannot be held, the best effort is made to hold as
2259 /// much as possible. The remaining stake is forced withdrawn from the ledger.
2260 ///
2261 /// The fee is waived if the migration is successful.
2262 #[pallet::call_index(30)]
2263 #[pallet::weight(T::WeightInfo::migrate_currency())]
2264 pub fn migrate_currency(
2265 origin: OriginFor<T>,
2266 stash: T::AccountId,
2267 ) -> DispatchResultWithPostInfo {
2268 ensure_signed(origin)?;
2269 Self::do_migrate_currency(&stash)?;
2270
2271 // Refund the transaction fee if successful.
2272 Ok(Pays::No.into())
2273 }
2274
2275 /// This function allows governance to manually slash a validator and is a
2276 /// **fallback mechanism**.
2277 ///
2278 /// The dispatch origin must be `T::AdminOrigin`.
2279 ///
2280 /// ## Parameters
2281 /// - `validator_stash` - The stash account of the validator to slash.
2282 /// - `era` - The era in which the validator was in the active set.
2283 /// - `slash_fraction` - The percentage of the stake to slash, expressed as a Perbill.
2284 ///
2285 /// ## Behavior
2286 ///
2287 /// The slash will be applied using the standard slashing mechanics, respecting the
2288 /// configured `SlashDeferDuration`.
2289 ///
2290 /// This means:
2291 /// - If the validator was already slashed by a higher percentage for the same era, this
2292 /// slash will have no additional effect.
2293 /// - If the validator was previously slashed by a lower percentage, only the difference
2294 /// will be applied.
2295 /// - The slash will be deferred by `SlashDeferDuration` eras before being enacted.
2296 #[pallet::call_index(33)]
2297 #[pallet::weight(T::WeightInfo::manual_slash())]
2298 pub fn manual_slash(
2299 origin: OriginFor<T>,
2300 validator_stash: T::AccountId,
2301 era: EraIndex,
2302 slash_fraction: Perbill,
2303 ) -> DispatchResult {
2304 T::AdminOrigin::ensure_origin(origin)?;
2305
2306 // Check era is valid
2307 let current_era = CurrentEra::<T>::get().ok_or(Error::<T>::InvalidEraToReward)?;
2308 let history_depth = T::HistoryDepth::get();
2309 ensure!(
2310 era <= current_era && era >= current_era.saturating_sub(history_depth),
2311 Error::<T>::InvalidEraToReward
2312 );
2313
2314 let offence_details = sp_staking::offence::OffenceDetails {
2315 offender: validator_stash.clone(),
2316 reporters: Vec::new(),
2317 };
2318
2319 // Get the session index for the era
2320 let session_index =
2321 ErasStartSessionIndex::<T>::get(era).ok_or(Error::<T>::InvalidEraToReward)?;
2322
2323 // Create the offence and report it through on_offence system
2324 let _ = Self::on_offence(
2325 core::iter::once(offence_details),
2326 &[slash_fraction],
2327 session_index,
2328 );
2329
2330 Ok(())
2331 }
2332 }
2333}
2334
2335/// Check that list is sorted and has no duplicates.
2336fn is_sorted_and_unique(list: &[u32]) -> bool {
2337 list.windows(2).all(|w| w[0] < w[1])
2338}