referrerpolicy=no-referrer-when-downgrade

pallet_staking_async/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//! `pallet-staking-async`'s main `pallet` module.
19
20use crate::{
21	asset, session_rotation::EraElectionPlanner, slashing, weights::WeightInfo, AccountIdLookupOf,
22	ActiveEraInfo, BalanceOf, EraPayout, EraRewardPoints, ExposurePage, Forcing,
23	LedgerIntegrityState, MaxNominationsOf, NegativeImbalanceOf, Nominations, NominationsQuota,
24	PositiveImbalanceOf, RewardDestination, StakingLedger, UnappliedSlash, UnlockChunk,
25	ValidatorPrefs,
26};
27use alloc::{format, vec::Vec};
28use codec::Codec;
29use frame_election_provider_support::{ElectionProvider, SortedListProvider, VoteWeight};
30use frame_support::{
31	assert_ok,
32	pallet_prelude::*,
33	traits::{
34		fungible::{
35			hold::{Balanced as FunHoldBalanced, Mutate as FunHoldMutate},
36			Mutate, Mutate as FunMutate,
37		},
38		Contains, Defensive, DefensiveSaturating, EnsureOrigin, Get, InspectLockableCurrency,
39		Nothing, OnUnbalanced,
40	},
41	weights::Weight,
42	BoundedBTreeSet, BoundedVec,
43};
44use frame_system::{ensure_root, ensure_signed, pallet_prelude::*};
45pub use impls::*;
46use rand::seq::SliceRandom;
47use rand_chacha::{
48	rand_core::{RngCore, SeedableRng},
49	ChaChaRng,
50};
51use sp_core::{sr25519::Pair as SrPair, Pair};
52use sp_runtime::{
53	traits::{StaticLookup, Zero},
54	ArithmeticError, Perbill, Percent,
55};
56use sp_staking::{
57	EraIndex, Page, SessionIndex,
58	StakingAccount::{self, Controller, Stash},
59	StakingInterface,
60};
61
62mod impls;
63
64#[frame_support::pallet]
65pub mod pallet {
66	use core::ops::Deref;
67
68	use super::*;
69	use crate::{session_rotation, PagedExposureMetadata, SnapshotStatus};
70	use codec::HasCompact;
71	use frame_election_provider_support::{ElectionDataProvider, PageIndex};
72	use frame_support::{weights::WeightMeter, DefaultNoBound};
73
74	/// Represents the current step in the era pruning process
75	#[derive(Encode, Decode, Clone, Copy, PartialEq, Eq, Debug, TypeInfo, MaxEncodedLen)]
76	pub enum PruningStep {
77		/// Pruning ErasStakersPaged storage
78		ErasStakersPaged,
79		/// Pruning ErasStakersOverview storage
80		ErasStakersOverview,
81		/// Pruning ErasValidatorPrefs storage
82		ErasValidatorPrefs,
83		/// Pruning ClaimedRewards storage
84		ClaimedRewards,
85		/// Pruning ErasValidatorReward storage
86		ErasValidatorReward,
87		/// Pruning ErasRewardPoints storage
88		ErasRewardPoints,
89		/// Pruning ErasTotalStake storage
90		ErasTotalStake,
91	}
92
93	/// The in-code storage version.
94	const STORAGE_VERSION: StorageVersion = StorageVersion::new(17);
95
96	#[pallet::pallet]
97	#[pallet::storage_version(STORAGE_VERSION)]
98	pub struct Pallet<T>(_);
99
100	/// Possible operations on the configuration values of this pallet.
101	#[derive(TypeInfo, Debug, Clone, Encode, Decode, DecodeWithMemTracking, PartialEq)]
102	pub enum ConfigOp<T: Default + Codec> {
103		/// Don't change.
104		Noop,
105		/// Set the given value.
106		Set(T),
107		/// Remove from storage.
108		Remove,
109	}
110
111	#[pallet::config(with_default)]
112	pub trait Config: frame_system::Config {
113		/// The old trait for staking balance. Deprecated and only used for migrating old ledgers.
114		#[pallet::no_default]
115		type OldCurrency: InspectLockableCurrency<
116			Self::AccountId,
117			Moment = BlockNumberFor<Self>,
118			Balance = Self::CurrencyBalance,
119		>;
120
121		/// The staking balance.
122		#[pallet::no_default]
123		type Currency: FunHoldMutate<
124				Self::AccountId,
125				Reason = Self::RuntimeHoldReason,
126				Balance = Self::CurrencyBalance,
127			> + FunMutate<Self::AccountId, Balance = Self::CurrencyBalance>
128			+ FunHoldBalanced<Self::AccountId, Balance = Self::CurrencyBalance>;
129
130		/// Overarching hold reason.
131		#[pallet::no_default_bounds]
132		type RuntimeHoldReason: From<HoldReason>;
133
134		/// Just the `Currency::Balance` type; we have this item to allow us to constrain it to
135		/// `From<u64>`.
136		type CurrencyBalance: sp_runtime::traits::AtLeast32BitUnsigned
137			+ codec::FullCodec
138			+ DecodeWithMemTracking
139			+ HasCompact<Type: DecodeWithMemTracking>
140			+ Copy
141			+ MaybeSerializeDeserialize
142			+ core::fmt::Debug
143			+ Default
144			+ From<u64>
145			+ TypeInfo
146			+ Send
147			+ Sync
148			+ MaxEncodedLen;
149
150		/// Convert a balance into a number used for election calculation. This must fit into a
151		/// `u64` but is allowed to be sensibly lossy. The `u64` is used to communicate with the
152		/// [`frame_election_provider_support`] crate which accepts u64 numbers and does operations
153		/// in 128.
154		/// Consequently, the backward convert is used convert the u128s from sp-elections back to a
155		/// [`BalanceOf`].
156		#[pallet::no_default_bounds]
157		type CurrencyToVote: sp_staking::currency_to_vote::CurrencyToVote<BalanceOf<Self>>;
158
159		/// Something that provides the election functionality.
160		#[pallet::no_default]
161		type ElectionProvider: ElectionProvider<
162			AccountId = Self::AccountId,
163			BlockNumber = BlockNumberFor<Self>,
164			// we only accept an election provider that has staking as data provider.
165			DataProvider = Pallet<Self>,
166		>;
167
168		/// Something that defines the maximum number of nominations per nominator.
169		#[pallet::no_default_bounds]
170		type NominationsQuota: NominationsQuota<BalanceOf<Self>>;
171
172		/// Number of eras to keep in history.
173		///
174		/// Following information is kept for eras in `[current_era -
175		/// HistoryDepth, current_era]`: `ErasValidatorPrefs`, `ErasValidatorReward`,
176		/// `ErasRewardPoints`, `ErasTotalStake`, `ClaimedRewards`,
177		/// `ErasStakersPaged`, `ErasStakersOverview`.
178		///
179		/// Must be more than the number of eras delayed by session.
180		/// I.e. active era must always be in history. I.e. `active_era >
181		/// current_era - history_depth` must be guaranteed.
182		///
183		/// If migrating an existing pallet from storage value to config value,
184		/// this should be set to same value or greater as in storage.
185		#[pallet::constant]
186		type HistoryDepth: Get<u32>;
187
188		/// Tokens have been minted and are unused for validator-reward.
189		/// See [Era payout](./index.html#era-payout).
190		#[pallet::no_default_bounds]
191		type RewardRemainder: OnUnbalanced<NegativeImbalanceOf<Self>>;
192
193		/// Handler for the unbalanced reduction when slashing a staker.
194		#[pallet::no_default_bounds]
195		type Slash: OnUnbalanced<NegativeImbalanceOf<Self>>;
196
197		/// Handler for the unbalanced increment when rewarding a staker.
198		/// NOTE: in most cases, the implementation of `OnUnbalanced` should modify the total
199		/// issuance.
200		#[pallet::no_default_bounds]
201		type Reward: OnUnbalanced<PositiveImbalanceOf<Self>>;
202
203		/// Number of sessions per era, as per the preferences of the **relay chain**.
204		#[pallet::constant]
205		type SessionsPerEra: Get<SessionIndex>;
206
207		/// Number of sessions before the end of an era when the election for the next era will
208		/// start.
209		///
210		/// - This determines how many sessions **before** the last session of the era the staking
211		///   election process should begin.
212		/// - The value is bounded between **1** (election starts at the beginning of the last
213		///   session) and `SessionsPerEra` (election starts at the beginning of the first session
214		///   of the era).
215		///
216		/// ### Example:
217		/// - If `SessionsPerEra = 6` and `PlanningEraOffset = 1`, the election starts at the
218		///   beginning of session `6 - 1 = 5`.
219		/// - If `PlanningEraOffset = 6`, the election starts at the beginning of session `6 - 6 =
220		///   0`, meaning it starts at the very beginning of the era.
221		#[pallet::constant]
222		type PlanningEraOffset: Get<SessionIndex>;
223
224		/// Number of eras that staked funds must remain bonded for.
225		#[pallet::constant]
226		type BondingDuration: Get<EraIndex>;
227
228		/// Number of eras that slashes are deferred by, after computation.
229		///
230		/// This should be less than the bonding duration. Set to 0 if slashes
231		/// should be applied immediately, without opportunity for intervention.
232		#[pallet::constant]
233		type SlashDeferDuration: Get<EraIndex>;
234
235		/// The origin which can manage less critical staking parameters that does not require root.
236		///
237		/// Supported actions: (1) cancel deferred slash, (2) set minimum commission.
238		#[pallet::no_default]
239		type AdminOrigin: EnsureOrigin<Self::RuntimeOrigin>;
240
241		/// The payout for validators and the system for the current era.
242		/// See [Era payout](./index.html#era-payout).
243		#[pallet::no_default]
244		type EraPayout: EraPayout<BalanceOf<Self>>;
245
246		/// The maximum size of each `T::ExposurePage`.
247		///
248		/// An `ExposurePage` is weakly bounded to a maximum of `MaxExposurePageSize`
249		/// nominators.
250		///
251		/// For older non-paged exposure, a reward payout was restricted to the top
252		/// `MaxExposurePageSize` nominators. This is to limit the i/o cost for the
253		/// nominator payout.
254		///
255		/// Note: `MaxExposurePageSize` is used to bound `ClaimedRewards` and is unsafe to
256		/// reduce without handling it in a migration.
257		#[pallet::constant]
258		type MaxExposurePageSize: Get<u32>;
259
260		/// The absolute maximum of winner validators this pallet should return.
261		///
262		/// As this pallet supports multi-block election, the set of winner validators *per
263		/// election* is bounded by this type.
264		#[pallet::constant]
265		type MaxValidatorSet: Get<u32>;
266
267		/// Something that provides a best-effort sorted list of voters aka electing nominators,
268		/// used for NPoS election.
269		///
270		/// The changes to nominators are reported to this. Moreover, each validator's self-vote is
271		/// also reported as one independent vote.
272		///
273		/// To keep the load off the chain as much as possible, changes made to the staked amount
274		/// via rewards and slashes are not reported and thus need to be manually fixed by the
275		/// staker. In case of `bags-list`, this always means using `rebag` and `putInFrontOf`.
276		///
277		/// Invariant: what comes out of this list will always be a nominator.
278		#[pallet::no_default]
279		type VoterList: SortedListProvider<Self::AccountId, Score = VoteWeight>;
280
281		/// WIP: This is a noop as of now, the actual business logic that's described below is going
282		/// to be introduced in a follow-up PR.
283		///
284		/// Something that provides a best-effort sorted list of targets aka electable validators,
285		/// used for NPoS election.
286		///
287		/// The changes to the approval stake of each validator are reported to this. This means any
288		/// change to:
289		/// 1. The stake of any validator or nominator.
290		/// 2. The targets of any nominator
291		/// 3. The role of any staker (e.g. validator -> chilled, nominator -> validator, etc)
292		///
293		/// Unlike `VoterList`, the values in this list are always kept up to date with reward and
294		/// slash as well, and thus represent the accurate approval stake of all account being
295		/// nominated by nominators.
296		///
297		/// Note that while at the time of nomination, all targets are checked to be real
298		/// validators, they can chill at any point, and their approval stakes will still be
299		/// recorded. This implies that what comes out of iterating this list MIGHT NOT BE AN ACTIVE
300		/// VALIDATOR.
301		#[pallet::no_default]
302		type TargetList: SortedListProvider<Self::AccountId, Score = BalanceOf<Self>>;
303
304		/// The maximum number of `unlocking` chunks a [`StakingLedger`] can
305		/// have. Effectively determines how many unique eras a staker may be
306		/// unbonding in.
307		///
308		/// Note: `MaxUnlockingChunks` is used as the upper bound for the
309		/// `BoundedVec` item `StakingLedger.unlocking`. Setting this value
310		/// lower than the existing value can lead to inconsistencies in the
311		/// `StakingLedger` and will need to be handled properly in a runtime
312		/// migration. The test `reducing_max_unlocking_chunks_abrupt` shows
313		/// this effect.
314		#[pallet::constant]
315		type MaxUnlockingChunks: Get<u32>;
316
317		/// The maximum amount of controller accounts that can be deprecated in one call.
318		type MaxControllersInDeprecationBatch: Get<u32>;
319
320		/// Something that listens to staking updates and performs actions based on the data it
321		/// receives.
322		///
323		/// WARNING: this only reports slashing and withdraw events for the time being.
324		#[pallet::no_default_bounds]
325		type EventListeners: sp_staking::OnStakingUpdate<Self::AccountId, BalanceOf<Self>>;
326
327		/// Maximum allowed era duration in milliseconds.
328		///
329		/// This provides a defensive upper bound to cap the effective era duration, preventing
330		/// excessively long eras from causing runaway inflation (e.g., due to bugs). If the actual
331		/// era duration exceeds this value, it will be clamped to this maximum.
332		///
333		/// Example: For an ideal era duration of 24 hours (86,400,000 ms),
334		/// this can be set to 604,800,000 ms (7 days).
335		#[pallet::constant]
336		type MaxEraDuration: Get<u64>;
337
338		/// Maximum number of storage items that can be pruned in a single call.
339		///
340		/// This controls how many storage items can be deleted in each call to `prune_era_step`.
341		/// This should be set to a conservative value (e.g., 100-500 items) to ensure pruning
342		/// doesn't consume too much block space. The actual weight is determined by benchmarks.
343		#[pallet::constant]
344		type MaxPruningItems: Get<u32>;
345
346		/// Interface to talk to the RC-Client pallet, possibly sending election results to the
347		/// relay chain.
348		#[pallet::no_default]
349		type RcClientInterface: pallet_staking_async_rc_client::RcClientInterface<
350			AccountId = Self::AccountId,
351		>;
352
353		#[pallet::no_default_bounds]
354		/// Filter some accounts from participating in staking.
355		///
356		/// This is useful for example to blacklist an account that is participating in staking in
357		/// another way (such as pools).
358		type Filter: Contains<Self::AccountId>;
359
360		/// Weight information for extrinsics in this pallet.
361		type WeightInfo: WeightInfo;
362	}
363
364	/// A reason for placing a hold on funds.
365	#[pallet::composite_enum]
366	pub enum HoldReason {
367		/// Funds on stake by a nominator or a validator.
368		#[codec(index = 0)]
369		Staking,
370	}
371
372	/// Default implementations of [`DefaultConfig`], which can be used to implement [`Config`].
373	pub mod config_preludes {
374		use super::*;
375		use frame_support::{derive_impl, parameter_types, traits::ConstU32};
376		pub struct TestDefaultConfig;
377
378		#[derive_impl(frame_system::config_preludes::TestDefaultConfig, no_aggregated_types)]
379		impl frame_system::DefaultConfig for TestDefaultConfig {}
380
381		parameter_types! {
382			pub const SessionsPerEra: SessionIndex = 3;
383			pub const BondingDuration: EraIndex = 3;
384			pub const MaxPruningItems: u32 = 100;
385		}
386
387		#[frame_support::register_default_impl(TestDefaultConfig)]
388		impl DefaultConfig for TestDefaultConfig {
389			#[inject_runtime_type]
390			type RuntimeHoldReason = ();
391			type CurrencyBalance = u128;
392			type CurrencyToVote = ();
393			type NominationsQuota = crate::FixedNominationsQuota<16>;
394			type HistoryDepth = ConstU32<84>;
395			type RewardRemainder = ();
396			type Slash = ();
397			type Reward = ();
398			type SessionsPerEra = SessionsPerEra;
399			type BondingDuration = BondingDuration;
400			type PlanningEraOffset = ConstU32<1>;
401			type SlashDeferDuration = ();
402			type MaxExposurePageSize = ConstU32<64>;
403			type MaxUnlockingChunks = ConstU32<32>;
404			type MaxValidatorSet = ConstU32<100>;
405			type MaxControllersInDeprecationBatch = ConstU32<100>;
406			type MaxEraDuration = ();
407			type MaxPruningItems = MaxPruningItems;
408			type EventListeners = ();
409			type Filter = Nothing;
410			type WeightInfo = ();
411		}
412	}
413
414	/// The ideal number of active validators.
415	#[pallet::storage]
416	pub type ValidatorCount<T> = StorageValue<_, u32, ValueQuery>;
417
418	/// Map from all locked "stash" accounts to the controller account.
419	///
420	/// TWOX-NOTE: SAFE since `AccountId` is a secure hash.
421	#[pallet::storage]
422	pub type Bonded<T: Config> = StorageMap<_, Twox64Concat, T::AccountId, T::AccountId>;
423
424	/// The minimum active bond to become and maintain the role of a nominator.
425	#[pallet::storage]
426	pub type MinNominatorBond<T: Config> = StorageValue<_, BalanceOf<T>, ValueQuery>;
427
428	/// The minimum active bond to become and maintain the role of a validator.
429	#[pallet::storage]
430	pub type MinValidatorBond<T: Config> = StorageValue<_, BalanceOf<T>, ValueQuery>;
431
432	/// The minimum active nominator stake of the last successful election.
433	#[pallet::storage]
434	pub type MinimumActiveStake<T> = StorageValue<_, BalanceOf<T>, ValueQuery>;
435
436	/// The minimum amount of commission that validators can set.
437	///
438	/// If set to `0`, no limit exists.
439	#[pallet::storage]
440	pub type MinCommission<T: Config> = StorageValue<_, Perbill, ValueQuery>;
441
442	/// Map from all (unlocked) "controller" accounts to the info regarding the staking.
443	///
444	/// Note: All the reads and mutations to this storage *MUST* be done through the methods exposed
445	/// by [`StakingLedger`] to ensure data and lock consistency.
446	#[pallet::storage]
447	pub type Ledger<T: Config> = StorageMap<_, Blake2_128Concat, T::AccountId, StakingLedger<T>>;
448
449	/// Where the reward payment should be made. Keyed by stash.
450	///
451	/// TWOX-NOTE: SAFE since `AccountId` is a secure hash.
452	#[pallet::storage]
453	pub type Payee<T: Config> =
454		StorageMap<_, Twox64Concat, T::AccountId, RewardDestination<T::AccountId>, OptionQuery>;
455
456	/// The map from (wannabe) validator stash key to the preferences of that validator.
457	///
458	/// TWOX-NOTE: SAFE since `AccountId` is a secure hash.
459	#[pallet::storage]
460	pub type Validators<T: Config> =
461		CountedStorageMap<_, Twox64Concat, T::AccountId, ValidatorPrefs, ValueQuery>;
462
463	/// The maximum validator count before we stop allowing new validators to join.
464	///
465	/// When this value is not set, no limits are enforced.
466	#[pallet::storage]
467	pub type MaxValidatorsCount<T> = StorageValue<_, u32, OptionQuery>;
468
469	/// The map from nominator stash key to their nomination preferences, namely the validators that
470	/// they wish to support.
471	///
472	/// Note that the keys of this storage map might become non-decodable in case the
473	/// account's [`NominationsQuota::MaxNominations`] configuration is decreased.
474	/// In this rare case, these nominators
475	/// are still existent in storage, their key is correct and retrievable (i.e. `contains_key`
476	/// indicates that they exist), but their value cannot be decoded. Therefore, the non-decodable
477	/// nominators will effectively not-exist, until they re-submit their preferences such that it
478	/// is within the bounds of the newly set `Config::MaxNominations`.
479	///
480	/// This implies that `::iter_keys().count()` and `::iter().count()` might return different
481	/// values for this map. Moreover, the main `::count()` is aligned with the former, namely the
482	/// number of keys that exist.
483	///
484	/// Lastly, if any of the nominators become non-decodable, they can be chilled immediately via
485	/// [`Call::chill_other`] dispatchable by anyone.
486	///
487	/// TWOX-NOTE: SAFE since `AccountId` is a secure hash.
488	#[pallet::storage]
489	pub type Nominators<T: Config> =
490		CountedStorageMap<_, Twox64Concat, T::AccountId, Nominations<T>>;
491
492	/// Stakers whose funds are managed by other pallets.
493	///
494	/// This pallet does not apply any locks on them, therefore they are only virtually bonded. They
495	/// are expected to be keyless accounts and hence should not be allowed to mutate their ledger
496	/// directly via this pallet. Instead, these accounts are managed by other pallets and accessed
497	/// via low level apis. We keep track of them to do minimal integrity checks.
498	#[pallet::storage]
499	pub type VirtualStakers<T: Config> = CountedStorageMap<_, Twox64Concat, T::AccountId, ()>;
500
501	/// The maximum nominator count before we stop allowing new validators to join.
502	///
503	/// When this value is not set, no limits are enforced.
504	#[pallet::storage]
505	pub type MaxNominatorsCount<T> = StorageValue<_, u32, OptionQuery>;
506
507	// --- AUDIT NOTE: the following storage items should only be controlled by `Rotator`
508
509	/// The current planned era index.
510	///
511	/// This is the latest planned era, depending on how the Session pallet queues the validator
512	/// set, it might be active or not.
513	#[pallet::storage]
514	pub type CurrentEra<T> = StorageValue<_, EraIndex>;
515
516	/// The active era information, it holds index and start.
517	///
518	/// The active era is the era being currently rewarded. Validator set of this era must be
519	/// equal to what is RC's session pallet.
520	#[pallet::storage]
521	pub type ActiveEra<T> = StorageValue<_, ActiveEraInfo>;
522
523	/// Custom bound for [`BondedEras`] which is equal to [`Config::BondingDuration`] + 1.
524	pub struct BondedErasBound<T>(core::marker::PhantomData<T>);
525	impl<T: Config> Get<u32> for BondedErasBound<T> {
526		fn get() -> u32 {
527			T::BondingDuration::get().saturating_add(1)
528		}
529	}
530
531	/// A mapping from still-bonded eras to the first session index of that era.
532	///
533	/// Must contains information for eras for the range:
534	/// `[active_era - bounding_duration; active_era]`
535	#[pallet::storage]
536	pub type BondedEras<T: Config> =
537		StorageValue<_, BoundedVec<(EraIndex, SessionIndex), BondedErasBound<T>>, ValueQuery>;
538
539	// --- AUDIT Note: end of storage items controlled by `Rotator`.
540
541	/// Summary of validator exposure at a given era.
542	///
543	/// This contains the total stake in support of the validator and their own stake. In addition,
544	/// it can also be used to get the number of nominators backing this validator and the number of
545	/// exposure pages they are divided into. The page count is useful to determine the number of
546	/// pages of rewards that needs to be claimed.
547	///
548	/// This is keyed first by the era index to allow bulk deletion and then the stash account.
549	/// Should only be accessed through `Eras`.
550	///
551	/// Is it removed after [`Config::HistoryDepth`] eras.
552	/// If stakers hasn't been set or has been removed then empty overview is returned.
553	#[pallet::storage]
554	pub type ErasStakersOverview<T: Config> = StorageDoubleMap<
555		_,
556		Twox64Concat,
557		EraIndex,
558		Twox64Concat,
559		T::AccountId,
560		PagedExposureMetadata<BalanceOf<T>>,
561		OptionQuery,
562	>;
563
564	/// A bounded wrapper for [`sp_staking::ExposurePage`].
565	///
566	/// It has `Deref` and `DerefMut` impls that map it back [`sp_staking::ExposurePage`] for all
567	/// purposes. This is done in such a way because we prefer to keep the types in [`sp_staking`]
568	/// pure, and not polluted by pallet-specific bounding logic.
569	///
570	/// It encoded and decodes exactly the same as [`sp_staking::ExposurePage`], and provides a
571	/// manual `MaxEncodedLen` implementation, to be used in benchmarking
572	#[derive(PartialEqNoBound, Encode, Decode, DebugNoBound, TypeInfo, DefaultNoBound)]
573	#[scale_info(skip_type_params(T))]
574	pub struct BoundedExposurePage<T: Config>(pub ExposurePage<T::AccountId, BalanceOf<T>>);
575	impl<T: Config> Deref for BoundedExposurePage<T> {
576		type Target = ExposurePage<T::AccountId, BalanceOf<T>>;
577
578		fn deref(&self) -> &Self::Target {
579			&self.0
580		}
581	}
582
583	impl<T: Config> core::ops::DerefMut for BoundedExposurePage<T> {
584		fn deref_mut(&mut self) -> &mut Self::Target {
585			&mut self.0
586		}
587	}
588
589	impl<T: Config> codec::MaxEncodedLen for BoundedExposurePage<T> {
590		fn max_encoded_len() -> usize {
591			let max_exposure_page_size = T::MaxExposurePageSize::get() as usize;
592			let individual_size =
593				T::AccountId::max_encoded_len() + BalanceOf::<T>::max_encoded_len();
594
595			// 1 balance for `total`
596			BalanceOf::<T>::max_encoded_len() +
597			// individual_size multiplied by page size
598				max_exposure_page_size.saturating_mul(individual_size)
599		}
600	}
601
602	impl<T: Config> From<ExposurePage<T::AccountId, BalanceOf<T>>> for BoundedExposurePage<T> {
603		fn from(value: ExposurePage<T::AccountId, BalanceOf<T>>) -> Self {
604			Self(value)
605		}
606	}
607
608	impl<T: Config> From<BoundedExposurePage<T>> for ExposurePage<T::AccountId, BalanceOf<T>> {
609		fn from(value: BoundedExposurePage<T>) -> Self {
610			value.0
611		}
612	}
613
614	impl<T: Config> codec::EncodeLike<BoundedExposurePage<T>>
615		for ExposurePage<T::AccountId, BalanceOf<T>>
616	{
617	}
618
619	/// Paginated exposure of a validator at given era.
620	///
621	/// This is keyed first by the era index to allow bulk deletion, then stash account and finally
622	/// the page. Should only be accessed through `Eras`.
623	///
624	/// This is cleared after [`Config::HistoryDepth`] eras.
625	#[pallet::storage]
626	pub type ErasStakersPaged<T: Config> = StorageNMap<
627		_,
628		(
629			NMapKey<Twox64Concat, EraIndex>,
630			NMapKey<Twox64Concat, T::AccountId>,
631			NMapKey<Twox64Concat, Page>,
632		),
633		BoundedExposurePage<T>,
634		OptionQuery,
635	>;
636
637	pub struct ClaimedRewardsBound<T>(core::marker::PhantomData<T>);
638	impl<T: Config> Get<u32> for ClaimedRewardsBound<T> {
639		fn get() -> u32 {
640			let max_total_nominators_per_validator =
641				<T::ElectionProvider as ElectionProvider>::MaxBackersPerWinnerFinal::get();
642			let exposure_page_size = T::MaxExposurePageSize::get();
643			max_total_nominators_per_validator
644				.saturating_div(exposure_page_size)
645				.saturating_add(1)
646		}
647	}
648
649	/// History of claimed paged rewards by era and validator.
650	///
651	/// This is keyed by era and validator stash which maps to the set of page indexes which have
652	/// been claimed.
653	///
654	/// It is removed after [`Config::HistoryDepth`] eras.
655	#[pallet::storage]
656	pub type ClaimedRewards<T: Config> = StorageDoubleMap<
657		_,
658		Twox64Concat,
659		EraIndex,
660		Twox64Concat,
661		T::AccountId,
662		WeakBoundedVec<Page, ClaimedRewardsBound<T>>,
663		ValueQuery,
664	>;
665
666	/// Exposure of validator at era with the preferences of validators.
667	///
668	/// This is keyed first by the era index to allow bulk deletion and then the stash account.
669	///
670	/// Is it removed after [`Config::HistoryDepth`] eras.
671	// If prefs hasn't been set or has been removed then 0 commission is returned.
672	#[pallet::storage]
673	pub type ErasValidatorPrefs<T: Config> = StorageDoubleMap<
674		_,
675		Twox64Concat,
676		EraIndex,
677		Twox64Concat,
678		T::AccountId,
679		ValidatorPrefs,
680		ValueQuery,
681	>;
682
683	/// The total validator era payout for the last [`Config::HistoryDepth`] eras.
684	///
685	/// Eras that haven't finished yet or has been removed doesn't have reward.
686	#[pallet::storage]
687	pub type ErasValidatorReward<T: Config> = StorageMap<_, Twox64Concat, EraIndex, BalanceOf<T>>;
688
689	/// Rewards for the last [`Config::HistoryDepth`] eras.
690	/// If reward hasn't been set or has been removed then 0 reward is returned.
691	#[pallet::storage]
692	pub type ErasRewardPoints<T: Config> =
693		StorageMap<_, Twox64Concat, EraIndex, EraRewardPoints<T>, ValueQuery>;
694
695	/// The total amount staked for the last [`Config::HistoryDepth`] eras.
696	/// If total hasn't been set or has been removed then 0 stake is returned.
697	#[pallet::storage]
698	pub type ErasTotalStake<T: Config> =
699		StorageMap<_, Twox64Concat, EraIndex, BalanceOf<T>, ValueQuery>;
700
701	/// Mode of era forcing.
702	#[pallet::storage]
703	pub type ForceEra<T> = StorageValue<_, Forcing, ValueQuery>;
704
705	/// Maximum staked rewards, i.e. the percentage of the era inflation that
706	/// is used for stake rewards.
707	/// See [Era payout](./index.html#era-payout).
708	#[pallet::storage]
709	pub type MaxStakedRewards<T> = StorageValue<_, Percent, OptionQuery>;
710
711	/// The percentage of the slash that is distributed to reporters.
712	///
713	/// The rest of the slashed value is handled by the `Slash`.
714	#[pallet::storage]
715	pub type SlashRewardFraction<T> = StorageValue<_, Perbill, ValueQuery>;
716
717	/// The amount of currency given to reporters of a slash event which was
718	/// canceled by extraordinary circumstances (e.g. governance).
719	#[pallet::storage]
720	pub type CanceledSlashPayout<T: Config> = StorageValue<_, BalanceOf<T>, ValueQuery>;
721
722	/// Stores reported offences in a queue until they are processed in subsequent blocks.
723	///
724	/// Each offence is recorded under the corresponding era index and the offending validator's
725	/// account. If an offence spans multiple pages, only one page is processed at a time. Offences
726	/// are handled sequentially, with their associated slashes computed and stored in
727	/// `UnappliedSlashes`. These slashes are then applied in a future era as determined by
728	/// `SlashDeferDuration`.
729	///
730	/// Any offences tied to an era older than `BondingDuration` are automatically dropped.
731	/// Processing always prioritizes the oldest era first.
732	#[pallet::storage]
733	pub type OffenceQueue<T: Config> = StorageDoubleMap<
734		_,
735		Twox64Concat,
736		EraIndex,
737		Twox64Concat,
738		T::AccountId,
739		slashing::OffenceRecord<T::AccountId>,
740	>;
741
742	/// Tracks the eras that contain offences in `OffenceQueue`, sorted from **earliest to latest**.
743	///
744	/// - This ensures efficient retrieval of the oldest offence without iterating through
745	/// `OffenceQueue`.
746	/// - When a new offence is added to `OffenceQueue`, its era is **inserted in sorted order**
747	/// if not already present.
748	/// - When all offences for an era are processed, it is **removed** from this list.
749	/// - The maximum length of this vector is bounded by `BondingDuration`.
750	///
751	/// This eliminates the need for expensive iteration and sorting when fetching the next offence
752	/// to process.
753	#[pallet::storage]
754	pub type OffenceQueueEras<T: Config> = StorageValue<_, WeakBoundedVec<u32, T::BondingDuration>>;
755
756	/// Tracks the currently processed offence record from the `OffenceQueue`.
757	///
758	/// - When processing offences, an offence record is **popped** from the oldest era in
759	///   `OffenceQueue` and stored here.
760	/// - The function `process_offence` reads from this storage, processing one page of exposure at
761	///   a time.
762	/// - After processing a page, the `exposure_page` count is **decremented** until it reaches
763	///   zero.
764	/// - Once fully processed, the offence record is removed from this storage.
765	///
766	/// This ensures that offences are processed incrementally, preventing excessive computation
767	/// in a single block while maintaining correct slashing behavior.
768	#[pallet::storage]
769	pub type ProcessingOffence<T: Config> =
770		StorageValue<_, (EraIndex, T::AccountId, slashing::OffenceRecord<T::AccountId>)>;
771
772	/// All unapplied slashes that are queued for later.
773	#[pallet::storage]
774	pub type UnappliedSlashes<T: Config> = StorageDoubleMap<
775		_,
776		Twox64Concat,
777		EraIndex,
778		Twox64Concat,
779		// Unique key for unapplied slashes: (validator, slash fraction, page index).
780		(T::AccountId, Perbill, u32),
781		UnappliedSlash<T>,
782		OptionQuery,
783	>;
784
785	/// Cancelled slashes by era and validator with maximum slash fraction to be cancelled.
786	///
787	/// When slashes are cancelled by governance, this stores the era and the validators
788	/// whose slashes should be cancelled, along with the maximum slash fraction that should
789	/// be cancelled for each validator.
790	#[pallet::storage]
791	pub type CancelledSlashes<T: Config> = StorageMap<
792		_,
793		Twox64Concat,
794		EraIndex,
795		BoundedVec<(T::AccountId, Perbill), T::MaxValidatorSet>,
796		ValueQuery,
797	>;
798
799	/// All slashing events on validators, mapped by era to the highest slash proportion
800	/// and slash value of the era.
801	#[pallet::storage]
802	pub type ValidatorSlashInEra<T: Config> = StorageDoubleMap<
803		_,
804		Twox64Concat,
805		EraIndex,
806		Twox64Concat,
807		T::AccountId,
808		(Perbill, BalanceOf<T>),
809	>;
810
811	/// The threshold for when users can start calling `chill_other` for other validators /
812	/// nominators. The threshold is compared to the actual number of validators / nominators
813	/// (`CountFor*`) in the system compared to the configured max (`Max*Count`).
814	#[pallet::storage]
815	pub type ChillThreshold<T: Config> = StorageValue<_, Percent, OptionQuery>;
816
817	/// Voter snapshot progress status.
818	///
819	/// If the status is `Ongoing`, it keeps a cursor of the last voter retrieved to proceed when
820	/// creating the next snapshot page.
821	#[pallet::storage]
822	pub type VoterSnapshotStatus<T: Config> =
823		StorageValue<_, SnapshotStatus<T::AccountId>, ValueQuery>;
824
825	/// Keeps track of an ongoing multi-page election solution request.
826	///
827	/// If `Some(_)``, it is the next page that we intend to elect. If `None`, we are not in the
828	/// election process.
829	///
830	/// This is only set in multi-block elections. Should always be `None` otherwise.
831	#[pallet::storage]
832	pub type NextElectionPage<T: Config> = StorageValue<_, PageIndex, OptionQuery>;
833
834	/// A bounded list of the "electable" stashes that resulted from a successful election.
835	#[pallet::storage]
836	pub type ElectableStashes<T: Config> =
837		StorageValue<_, BoundedBTreeSet<T::AccountId, T::MaxValidatorSet>, ValueQuery>;
838
839	/// Tracks the current step of era pruning process for each era being lazily pruned.
840	#[pallet::storage]
841	pub type EraPruningState<T: Config> = StorageMap<_, Twox64Concat, EraIndex, PruningStep>;
842
843	#[pallet::genesis_config]
844	#[derive(frame_support::DefaultNoBound, frame_support::DebugNoBound)]
845	pub struct GenesisConfig<T: Config> {
846		pub validator_count: u32,
847		pub force_era: Forcing,
848		pub slash_reward_fraction: Perbill,
849		pub canceled_payout: BalanceOf<T>,
850		pub stakers: Vec<(T::AccountId, BalanceOf<T>, crate::StakerStatus<T::AccountId>)>,
851		pub min_nominator_bond: BalanceOf<T>,
852		pub min_validator_bond: BalanceOf<T>,
853		pub max_validator_count: Option<u32>,
854		pub max_nominator_count: Option<u32>,
855		/// Create the given number of validators and nominators.
856		///
857		/// These account need not be in the endowment list of balances, and are auto-topped up
858		/// here.
859		///
860		/// Useful for testing genesis config.
861		pub dev_stakers: Option<(u32, u32)>,
862		/// initial active era, corresponding session index and start timestamp.
863		pub active_era: (u32, u32, u64),
864	}
865
866	impl<T: Config> GenesisConfig<T> {
867		fn generate_endowed_bonded_account(derivation: &str, rng: &mut ChaChaRng) -> T::AccountId {
868			let pair: SrPair = Pair::from_string(&derivation, None)
869				.expect(&format!("Failed to parse derivation string: {derivation}"));
870			let who = T::AccountId::decode(&mut &pair.public().encode()[..])
871				.expect(&format!("Failed to decode public key from pair: {:?}", pair.public()));
872
873			let (min, max) = T::VoterList::range();
874			let stake = BalanceOf::<T>::from(rng.next_u64().min(max).max(min));
875			let two: BalanceOf<T> = 2u32.into();
876
877			assert_ok!(T::Currency::mint_into(&who, stake * two));
878			assert_ok!(<Pallet<T>>::bond(
879				T::RuntimeOrigin::from(Some(who.clone()).into()),
880				stake,
881				RewardDestination::Staked,
882			));
883			who
884		}
885	}
886
887	#[pallet::genesis_build]
888	impl<T: Config> BuildGenesisConfig for GenesisConfig<T> {
889		fn build(&self) {
890			crate::log!(trace, "initializing with {:?}", self);
891			assert!(
892				self.validator_count <=
893					<T::ElectionProvider as ElectionProvider>::MaxWinnersPerPage::get() *
894						<T::ElectionProvider as ElectionProvider>::Pages::get(),
895				"validator count is too high, `ElectionProvider` can never fulfill this"
896			);
897			ValidatorCount::<T>::put(self.validator_count);
898
899			ForceEra::<T>::put(self.force_era);
900			CanceledSlashPayout::<T>::put(self.canceled_payout);
901			SlashRewardFraction::<T>::put(self.slash_reward_fraction);
902			MinNominatorBond::<T>::put(self.min_nominator_bond);
903			MinValidatorBond::<T>::put(self.min_validator_bond);
904			if let Some(x) = self.max_validator_count {
905				MaxValidatorsCount::<T>::put(x);
906			}
907			if let Some(x) = self.max_nominator_count {
908				MaxNominatorsCount::<T>::put(x);
909			}
910
911			// First pass: set up all validators and idle stakers
912			for &(ref stash, balance, ref status) in &self.stakers {
913				match status {
914					crate::StakerStatus::Validator => {
915						crate::log!(
916							trace,
917							"inserting genesis validator: {:?} => {:?} => {:?}",
918							stash,
919							balance,
920							status
921						);
922						assert!(
923							asset::free_to_stake::<T>(stash) >= balance,
924							"Stash does not have enough balance to bond."
925						);
926						assert_ok!(<Pallet<T>>::bond(
927							T::RuntimeOrigin::from(Some(stash.clone()).into()),
928							balance,
929							RewardDestination::Staked,
930						));
931						assert_ok!(<Pallet<T>>::validate(
932							T::RuntimeOrigin::from(Some(stash.clone()).into()),
933							Default::default(),
934						));
935					},
936					crate::StakerStatus::Idle => {
937						crate::log!(
938							trace,
939							"inserting genesis idle staker: {:?} => {:?} => {:?}",
940							stash,
941							balance,
942							status
943						);
944						assert!(
945							asset::free_to_stake::<T>(stash) >= balance,
946							"Stash does not have enough balance to bond."
947						);
948						assert_ok!(<Pallet<T>>::bond(
949							T::RuntimeOrigin::from(Some(stash.clone()).into()),
950							balance,
951							RewardDestination::Staked,
952						));
953					},
954					_ => {},
955				}
956			}
957
958			// Second pass: set up all nominators (now that validators exist)
959			for &(ref stash, balance, ref status) in &self.stakers {
960				match status {
961					crate::StakerStatus::Nominator(votes) => {
962						crate::log!(
963							trace,
964							"inserting genesis nominator: {:?} => {:?} => {:?}",
965							stash,
966							balance,
967							status
968						);
969						assert!(
970							asset::free_to_stake::<T>(stash) >= balance,
971							"Stash does not have enough balance to bond."
972						);
973						assert_ok!(<Pallet<T>>::bond(
974							T::RuntimeOrigin::from(Some(stash.clone()).into()),
975							balance,
976							RewardDestination::Staked,
977						));
978						assert_ok!(<Pallet<T>>::nominate(
979							T::RuntimeOrigin::from(Some(stash.clone()).into()),
980							votes.iter().map(|l| T::Lookup::unlookup(l.clone())).collect(),
981						));
982					},
983					_ => {},
984				}
985			}
986
987			// all voters are reported to the `VoterList`.
988			assert_eq!(
989				T::VoterList::count(),
990				Nominators::<T>::count() + Validators::<T>::count(),
991				"not all genesis stakers were inserted into sorted list provider, something is wrong."
992			);
993
994			// now generate the dev stakers, after all else is setup
995			if let Some((validators, nominators)) = self.dev_stakers {
996				crate::log!(
997					debug,
998					"generating dev stakers: validators: {}, nominators: {}",
999					validators,
1000					nominators
1001				);
1002				let base_derivation = "//staker//{}";
1003
1004				// it is okay for the randomness to be the same on every call. If we want different,
1005				// we can make `base_derivation` configurable.
1006				let mut rng =
1007					ChaChaRng::from_seed(base_derivation.using_encoded(sp_core::blake2_256));
1008
1009				(0..validators).for_each(|index| {
1010					let derivation = base_derivation.replace("{}", &format!("validator{}", index));
1011					let who = Self::generate_endowed_bonded_account(&derivation, &mut rng);
1012					assert_ok!(<Pallet<T>>::validate(
1013						T::RuntimeOrigin::from(Some(who.clone()).into()),
1014						Default::default(),
1015					));
1016				});
1017
1018				// This allows us to work with configs like `dev_stakers: (0, 10)`. Don't create new
1019				// validators, just add a bunch of nominators. Useful for slashing tests.
1020				let all_validators = Validators::<T>::iter_keys().collect::<Vec<_>>();
1021
1022				(0..nominators).for_each(|index| {
1023					let derivation = base_derivation.replace("{}", &format!("nominator{}", index));
1024					let who = Self::generate_endowed_bonded_account(&derivation, &mut rng);
1025
1026					let random_nominations = all_validators
1027						.choose_multiple(&mut rng, MaxNominationsOf::<T>::get() as usize)
1028						.map(|v| v.clone())
1029						.collect::<Vec<_>>();
1030
1031					assert_ok!(<Pallet<T>>::nominate(
1032						T::RuntimeOrigin::from(Some(who.clone()).into()),
1033						random_nominations.iter().map(|l| T::Lookup::unlookup(l.clone())).collect(),
1034					));
1035				})
1036			}
1037
1038			let (active_era, session_index, timestamp) = self.active_era;
1039			ActiveEra::<T>::put(ActiveEraInfo { index: active_era, start: Some(timestamp) });
1040			// at genesis, we do not have any new planned era.
1041			CurrentEra::<T>::put(active_era);
1042			// set the bonded genesis era
1043			BondedEras::<T>::put(
1044				BoundedVec::<_, BondedErasBound<T>>::try_from(
1045					alloc::vec![(active_era, session_index)]
1046				)
1047				.expect("bound for BondedEras is BondingDuration + 1; can contain at least one element; qed")
1048			);
1049		}
1050	}
1051
1052	#[pallet::event]
1053	#[pallet::generate_deposit(pub fn deposit_event)]
1054	pub enum Event<T: Config> {
1055		/// The era payout has been set; the first balance is the validator-payout; the second is
1056		/// the remainder from the maximum amount of reward.
1057		EraPaid {
1058			era_index: EraIndex,
1059			validator_payout: BalanceOf<T>,
1060			remainder: BalanceOf<T>,
1061		},
1062		/// The nominator has been rewarded by this amount to this destination.
1063		Rewarded {
1064			stash: T::AccountId,
1065			dest: RewardDestination<T::AccountId>,
1066			amount: BalanceOf<T>,
1067		},
1068		/// A staker (validator or nominator) has been slashed by the given amount.
1069		Slashed {
1070			staker: T::AccountId,
1071			amount: BalanceOf<T>,
1072		},
1073		/// An old slashing report from a prior era was discarded because it could
1074		/// not be processed.
1075		OldSlashingReportDiscarded {
1076			session_index: SessionIndex,
1077		},
1078		/// An account has bonded this amount. \[stash, amount\]
1079		///
1080		/// NOTE: This event is only emitted when funds are bonded via a dispatchable. Notably,
1081		/// it will not be emitted for staking rewards when they are added to stake.
1082		Bonded {
1083			stash: T::AccountId,
1084			amount: BalanceOf<T>,
1085		},
1086		/// An account has unbonded this amount.
1087		Unbonded {
1088			stash: T::AccountId,
1089			amount: BalanceOf<T>,
1090		},
1091		/// An account has called `withdraw_unbonded` and removed unbonding chunks worth `Balance`
1092		/// from the unlocking queue.
1093		Withdrawn {
1094			stash: T::AccountId,
1095			amount: BalanceOf<T>,
1096		},
1097		/// A subsequent event of `Withdrawn`, indicating that `stash` was fully removed from the
1098		/// system.
1099		StakerRemoved {
1100			stash: T::AccountId,
1101		},
1102		/// A nominator has been kicked from a validator.
1103		Kicked {
1104			nominator: T::AccountId,
1105			stash: T::AccountId,
1106		},
1107		/// An account has stopped participating as either a validator or nominator.
1108		Chilled {
1109			stash: T::AccountId,
1110		},
1111		/// A Page of stakers rewards are getting paid. `next` is `None` if all pages are claimed.
1112		PayoutStarted {
1113			era_index: EraIndex,
1114			validator_stash: T::AccountId,
1115			page: Page,
1116			next: Option<Page>,
1117		},
1118		/// A validator has set their preferences.
1119		ValidatorPrefsSet {
1120			stash: T::AccountId,
1121			prefs: ValidatorPrefs,
1122		},
1123		/// Voters size limit reached.
1124		SnapshotVotersSizeExceeded {
1125			size: u32,
1126		},
1127		/// Targets size limit reached.
1128		SnapshotTargetsSizeExceeded {
1129			size: u32,
1130		},
1131		ForceEra {
1132			mode: Forcing,
1133		},
1134		/// Report of a controller batch deprecation.
1135		ControllerBatchDeprecated {
1136			failures: u32,
1137		},
1138		/// Staking balance migrated from locks to holds, with any balance that could not be held
1139		/// is force withdrawn.
1140		CurrencyMigrated {
1141			stash: T::AccountId,
1142			force_withdraw: BalanceOf<T>,
1143		},
1144		/// A page from a multi-page election was fetched. A number of these are followed by
1145		/// `StakersElected`.
1146		///
1147		/// `Ok(count)` indicates the give number of stashes were added.
1148		/// `Err(index)` indicates that the stashes after index were dropped.
1149		/// `Err(0)` indicates that an error happened but no stashes were dropped nor added.
1150		///
1151		/// The error indicates that a number of validators were dropped due to excess size, but
1152		/// the overall election will continue.
1153		PagedElectionProceeded {
1154			page: PageIndex,
1155			result: Result<u32, u32>,
1156		},
1157		/// An offence for the given validator, for the given percentage of their stake, at the
1158		/// given era as been reported.
1159		OffenceReported {
1160			offence_era: EraIndex,
1161			validator: T::AccountId,
1162			fraction: Perbill,
1163		},
1164		/// An offence has been processed and the corresponding slash has been computed.
1165		SlashComputed {
1166			offence_era: EraIndex,
1167			slash_era: EraIndex,
1168			offender: T::AccountId,
1169			page: u32,
1170		},
1171		/// An unapplied slash has been cancelled.
1172		SlashCancelled {
1173			slash_era: EraIndex,
1174			validator: T::AccountId,
1175		},
1176		/// Session change has been triggered.
1177		///
1178		/// If planned_era is one era ahead of active_era, it implies new era is being planned and
1179		/// election is ongoing.
1180		SessionRotated {
1181			starting_session: SessionIndex,
1182			active_era: EraIndex,
1183			planned_era: EraIndex,
1184		},
1185		/// Something occurred that should never happen under normal operation.
1186		/// Logged as an event for fail-safe observability.
1187		Unexpected(UnexpectedKind),
1188		/// An offence was reported that was too old to be processed, and thus was dropped.
1189		OffenceTooOld {
1190			offence_era: EraIndex,
1191			validator: T::AccountId,
1192			fraction: Perbill,
1193		},
1194		/// An old era with the given index was pruned.
1195		EraPruned {
1196			index: EraIndex,
1197		},
1198	}
1199
1200	/// Represents unexpected or invariant-breaking conditions encountered during execution.
1201	///
1202	/// These variants are emitted as [`Event::Unexpected`] and indicate a defensive check has
1203	/// failed. While these should never occur under normal operation, they are useful for
1204	/// diagnosing issues in production or test environments.
1205	#[derive(Clone, Encode, Decode, DecodeWithMemTracking, PartialEq, TypeInfo, Debug)]
1206	pub enum UnexpectedKind {
1207		/// Emitted when calculated era duration exceeds the configured maximum.
1208		EraDurationBoundExceeded,
1209		/// Received a validator activation event that is not recognized.
1210		UnknownValidatorActivation,
1211		/// Failed to proceed paged election due to weight limits
1212		PagedElectionOutOfWeight { page: PageIndex, required: Weight, had: Weight },
1213	}
1214
1215	#[pallet::error]
1216	#[derive(PartialEq)]
1217	pub enum Error<T> {
1218		/// Not a controller account.
1219		NotController,
1220		/// Not a stash account.
1221		NotStash,
1222		/// Stash is already bonded.
1223		AlreadyBonded,
1224		/// Controller is already paired.
1225		AlreadyPaired,
1226		/// Targets cannot be empty.
1227		EmptyTargets,
1228		/// Duplicate index.
1229		DuplicateIndex,
1230		/// Slash record not found.
1231		InvalidSlashRecord,
1232		/// Cannot bond, nominate or validate with value less than the minimum defined by
1233		/// governance (see `MinValidatorBond` and `MinNominatorBond`). If unbonding is the
1234		/// intention, `chill` first to remove one's role as validator/nominator.
1235		InsufficientBond,
1236		/// Can not schedule more unlock chunks.
1237		NoMoreChunks,
1238		/// Can not rebond without unlocking chunks.
1239		NoUnlockChunk,
1240		/// Attempting to target a stash that still has funds.
1241		FundedTarget,
1242		/// Invalid era to reward.
1243		InvalidEraToReward,
1244		/// Invalid number of nominations.
1245		InvalidNumberOfNominations,
1246		/// Rewards for this era have already been claimed for this validator.
1247		AlreadyClaimed,
1248		/// No nominators exist on this page.
1249		InvalidPage,
1250		/// Incorrect previous history depth input provided.
1251		IncorrectHistoryDepth,
1252		/// Internal state has become somehow corrupted and the operation cannot continue.
1253		BadState,
1254		/// Too many nomination targets supplied.
1255		TooManyTargets,
1256		/// A nomination target was supplied that was blocked or otherwise not a validator.
1257		BadTarget,
1258		/// The user has enough bond and thus cannot be chilled forcefully by an external person.
1259		CannotChillOther,
1260		/// There are too many nominators in the system. Governance needs to adjust the staking
1261		/// settings to keep things safe for the runtime.
1262		TooManyNominators,
1263		/// There are too many validator candidates in the system. Governance needs to adjust the
1264		/// staking settings to keep things safe for the runtime.
1265		TooManyValidators,
1266		/// Commission is too low. Must be at least `MinCommission`.
1267		CommissionTooLow,
1268		/// Some bound is not met.
1269		BoundNotMet,
1270		/// Used when attempting to use deprecated controller account logic.
1271		ControllerDeprecated,
1272		/// Cannot reset a ledger.
1273		CannotRestoreLedger,
1274		/// Provided reward destination is not allowed.
1275		RewardDestinationRestricted,
1276		/// Not enough funds available to withdraw.
1277		NotEnoughFunds,
1278		/// Operation not allowed for virtual stakers.
1279		VirtualStakerNotAllowed,
1280		/// Stash could not be reaped as other pallet might depend on it.
1281		CannotReapStash,
1282		/// The stake of this account is already migrated to `Fungible` holds.
1283		AlreadyMigrated,
1284		/// Era not yet started.
1285		EraNotStarted,
1286		/// Account is restricted from participation in staking. This may happen if the account is
1287		/// staking in another way already, such as via pool.
1288		Restricted,
1289		/// Unapplied slashes in the recently concluded era is blocking this operation.
1290		/// See `Call::apply_slash` to apply them.
1291		UnappliedSlashesInPreviousEra,
1292		/// The era is not eligible for pruning.
1293		EraNotPrunable,
1294		/// The slash has been cancelled and cannot be applied.
1295		CancelledSlash,
1296	}
1297
1298	impl<T: Config> Pallet<T> {
1299		/// Apply previously-unapplied slashes on the beginning of a new era, after a delay.
1300		pub fn apply_unapplied_slashes(active_era: EraIndex) -> Weight {
1301			let mut slashes = UnappliedSlashes::<T>::iter_prefix(&active_era).take(1);
1302			if let Some((key, slash)) = slashes.next() {
1303				crate::log!(
1304					debug,
1305					"🦹 found slash {:?} scheduled to be executed in era {:?}",
1306					slash,
1307					active_era,
1308				);
1309
1310				// Check if this slash has been cancelled
1311				if Self::check_slash_cancelled(active_era, &key.0, key.1) {
1312					crate::log!(
1313						debug,
1314						"🦹 slash for {:?} in era {:?} was cancelled, skipping",
1315						key.0,
1316						active_era,
1317					);
1318				} else {
1319					let offence_era = active_era.saturating_sub(T::SlashDeferDuration::get());
1320					slashing::apply_slash::<T>(slash, offence_era);
1321				}
1322
1323				// Always remove the slash from UnappliedSlashes
1324				UnappliedSlashes::<T>::remove(&active_era, &key);
1325
1326				// Check if there are more slashes for this era
1327				if UnappliedSlashes::<T>::iter_prefix(&active_era).next().is_none() {
1328					// No more slashes for this era, clear CancelledSlashes
1329					CancelledSlashes::<T>::remove(&active_era);
1330				}
1331
1332				T::WeightInfo::apply_slash()
1333			} else {
1334				// No slashes found for this era
1335				T::DbWeight::get().reads(1)
1336			}
1337		}
1338
1339		/// Execute one step of era pruning and get actual weight used
1340		fn do_prune_era_step(era: EraIndex) -> Result<Weight, DispatchError> {
1341			// Get current pruning state. If EraPruningState doesn't exist, it means:
1342			// - Era was never marked for pruning, OR
1343			// - Era was already fully pruned (pruning state was removed on final step)
1344			// In either case, this is an error - user should not call prune on non-prunable eras
1345			let current_step = EraPruningState::<T>::get(era).ok_or(Error::<T>::EraNotPrunable)?;
1346
1347			// Limit items to prevent deleting more than we can safely account for in weight
1348			// calculations
1349			let items_limit = T::MaxPruningItems::get().min(T::MaxValidatorSet::get());
1350
1351			let actual_weight = match current_step {
1352				PruningStep::ErasStakersPaged => {
1353					let result = ErasStakersPaged::<T>::clear_prefix((era,), items_limit, None);
1354					let items_deleted = result.backend as u32;
1355					result.maybe_cursor.is_none().then(|| {
1356						EraPruningState::<T>::insert(era, PruningStep::ErasStakersOverview)
1357					});
1358					T::WeightInfo::prune_era_stakers_paged(items_deleted)
1359				},
1360				PruningStep::ErasStakersOverview => {
1361					let result = ErasStakersOverview::<T>::clear_prefix(era, items_limit, None);
1362					let items_deleted = result.backend as u32;
1363					result.maybe_cursor.is_none().then(|| {
1364						EraPruningState::<T>::insert(era, PruningStep::ErasValidatorPrefs)
1365					});
1366					T::WeightInfo::prune_era_stakers_overview(items_deleted)
1367				},
1368				PruningStep::ErasValidatorPrefs => {
1369					let result = ErasValidatorPrefs::<T>::clear_prefix(era, items_limit, None);
1370					let items_deleted = result.backend as u32;
1371					result
1372						.maybe_cursor
1373						.is_none()
1374						.then(|| EraPruningState::<T>::insert(era, PruningStep::ClaimedRewards));
1375					T::WeightInfo::prune_era_validator_prefs(items_deleted)
1376				},
1377				PruningStep::ClaimedRewards => {
1378					let result = ClaimedRewards::<T>::clear_prefix(era, items_limit, None);
1379					let items_deleted = result.backend as u32;
1380					result.maybe_cursor.is_none().then(|| {
1381						EraPruningState::<T>::insert(era, PruningStep::ErasValidatorReward)
1382					});
1383					T::WeightInfo::prune_era_claimed_rewards(items_deleted)
1384				},
1385				PruningStep::ErasValidatorReward => {
1386					ErasValidatorReward::<T>::remove(era);
1387					EraPruningState::<T>::insert(era, PruningStep::ErasRewardPoints);
1388					T::WeightInfo::prune_era_validator_reward()
1389				},
1390				PruningStep::ErasRewardPoints => {
1391					ErasRewardPoints::<T>::remove(era);
1392					EraPruningState::<T>::insert(era, PruningStep::ErasTotalStake);
1393					T::WeightInfo::prune_era_reward_points()
1394				},
1395				PruningStep::ErasTotalStake => {
1396					ErasTotalStake::<T>::remove(era);
1397					// This is the final step - remove the pruning state
1398					EraPruningState::<T>::remove(era);
1399					T::WeightInfo::prune_era_total_stake()
1400				},
1401			};
1402
1403			// Check if era is fully pruned (pruning state removed) and emit event
1404			if EraPruningState::<T>::get(era).is_none() {
1405				Self::deposit_event(Event::<T>::EraPruned { index: era });
1406			}
1407
1408			Ok(actual_weight)
1409		}
1410	}
1411
1412	#[pallet::hooks]
1413	impl<T: Config> Hooks<BlockNumberFor<T>> for Pallet<T> {
1414		fn on_poll(_now: BlockNumberFor<T>, weight_meter: &mut WeightMeter) {
1415			let (weight, exec) = EraElectionPlanner::<T>::maybe_fetch_election_results();
1416			crate::log!(
1417				trace,
1418				"weight of fetching next election page is {:?}, have {:?}",
1419				weight,
1420				weight_meter.remaining()
1421			);
1422
1423			if weight_meter.can_consume(weight) {
1424				exec(weight_meter);
1425			} else {
1426				Self::deposit_event(Event::<T>::Unexpected(
1427					UnexpectedKind::PagedElectionOutOfWeight {
1428						page: NextElectionPage::<T>::get().unwrap_or(
1429							EraElectionPlanner::<T>::election_pages().defensive_saturating_sub(1),
1430						),
1431						required: weight,
1432						had: weight_meter.remaining(),
1433					},
1434				));
1435			}
1436		}
1437
1438		fn on_initialize(_now: BlockNumberFor<T>) -> Weight {
1439			// process our queue.
1440			let mut consumed_weight = slashing::process_offence::<T>();
1441
1442			// apply any pending slashes after `SlashDeferDuration`.
1443			consumed_weight.saturating_accrue(T::DbWeight::get().reads(1));
1444			if let Some(active_era) = ActiveEra::<T>::get() {
1445				let slash_weight = Self::apply_unapplied_slashes(active_era.index);
1446				consumed_weight.saturating_accrue(slash_weight);
1447			}
1448
1449			consumed_weight
1450		}
1451
1452		fn integrity_test() {
1453			// ensure that we funnel the correct value to the `DataProvider::MaxVotesPerVoter`;
1454			assert_eq!(
1455				MaxNominationsOf::<T>::get(),
1456				<Self as ElectionDataProvider>::MaxVotesPerVoter::get()
1457			);
1458
1459			// and that MaxNominations is always greater than 1, since we count on this.
1460			assert!(!MaxNominationsOf::<T>::get().is_zero());
1461
1462			assert!(
1463				T::SlashDeferDuration::get() < T::BondingDuration::get() || T::BondingDuration::get() == 0,
1464				"As per documentation, slash defer duration ({}) should be less than bonding duration ({}).",
1465				T::SlashDeferDuration::get(),
1466				T::BondingDuration::get(),
1467			);
1468
1469			// Ensure MaxPruningItems is reasonable (minimum 100 for efficiency)
1470			assert!(
1471				T::MaxPruningItems::get() >= 100,
1472				"MaxPruningItems must be at least 100 for efficient pruning, got: {}",
1473				T::MaxPruningItems::get()
1474			);
1475		}
1476
1477		#[cfg(feature = "try-runtime")]
1478		fn try_state(n: BlockNumberFor<T>) -> Result<(), sp_runtime::TryRuntimeError> {
1479			Self::do_try_state(n)
1480		}
1481	}
1482
1483	#[pallet::call]
1484	impl<T: Config> Pallet<T> {
1485		/// Take the origin account as a stash and lock up `value` of its balance. `controller` will
1486		/// be the account that controls it.
1487		///
1488		/// `value` must be more than the `minimum_balance` specified by `T::Currency`.
1489		///
1490		/// The dispatch origin for this call must be _Signed_ by the stash account.
1491		///
1492		/// Emits `Bonded`.
1493		///
1494		/// NOTE: Two of the storage writes (`Self::bonded`, `Self::payee`) are _never_ cleaned
1495		/// unless the `origin` falls below _existential deposit_ (or equal to 0) and gets removed
1496		/// as dust.
1497		#[pallet::call_index(0)]
1498		#[pallet::weight(T::WeightInfo::bond())]
1499		pub fn bond(
1500			origin: OriginFor<T>,
1501			#[pallet::compact] value: BalanceOf<T>,
1502			payee: RewardDestination<T::AccountId>,
1503		) -> DispatchResult {
1504			let stash = ensure_signed(origin)?;
1505
1506			ensure!(!T::Filter::contains(&stash), Error::<T>::Restricted);
1507
1508			if StakingLedger::<T>::is_bonded(StakingAccount::Stash(stash.clone())) {
1509				return Err(Error::<T>::AlreadyBonded.into());
1510			}
1511
1512			// An existing controller cannot become a stash.
1513			if StakingLedger::<T>::is_bonded(StakingAccount::Controller(stash.clone())) {
1514				return Err(Error::<T>::AlreadyPaired.into());
1515			}
1516
1517			// Reject a bond which is lower than the minimum bond.
1518			if value < Self::min_chilled_bond() {
1519				return Err(Error::<T>::InsufficientBond.into());
1520			}
1521
1522			let stash_balance = asset::free_to_stake::<T>(&stash);
1523			let value = value.min(stash_balance);
1524			Self::deposit_event(Event::<T>::Bonded { stash: stash.clone(), amount: value });
1525			let ledger = StakingLedger::<T>::new(stash.clone(), value);
1526
1527			// You're auto-bonded forever, here. We might improve this by only bonding when
1528			// you actually validate/nominate and remove once you unbond __everything__.
1529			ledger.bond(payee)?;
1530
1531			Ok(())
1532		}
1533
1534		/// Add some extra amount that have appeared in the stash `free_balance` into the balance up
1535		/// for staking.
1536		///
1537		/// The dispatch origin for this call must be _Signed_ by the stash, not the controller.
1538		///
1539		/// Use this if there are additional funds in your stash account that you wish to bond.
1540		/// Unlike [`bond`](Self::bond) or [`unbond`](Self::unbond) this function does not impose
1541		/// any limitation on the amount that can be added.
1542		///
1543		/// Emits `Bonded`.
1544		#[pallet::call_index(1)]
1545		#[pallet::weight(T::WeightInfo::bond_extra())]
1546		pub fn bond_extra(
1547			origin: OriginFor<T>,
1548			#[pallet::compact] max_additional: BalanceOf<T>,
1549		) -> DispatchResult {
1550			let stash = ensure_signed(origin)?;
1551			ensure!(!T::Filter::contains(&stash), Error::<T>::Restricted);
1552			Self::do_bond_extra(&stash, max_additional)
1553		}
1554
1555		/// Schedule a portion of the stash to be unlocked ready for transfer out after the bond
1556		/// period ends. If this leaves an amount actively bonded less than
1557		/// [`asset::existential_deposit`], then it is increased to the full amount.
1558		///
1559		/// The dispatch origin for this call must be _Signed_ by the controller, not the stash.
1560		///
1561		/// Once the unlock period is done, you can call `withdraw_unbonded` to actually move
1562		/// the funds out of management ready for transfer.
1563		///
1564		/// No more than a limited number of unlocking chunks (see `MaxUnlockingChunks`)
1565		/// can co-exists at the same time. If there are no unlocking chunks slots available
1566		/// [`Call::withdraw_unbonded`] is called to remove some of the chunks (if possible).
1567		///
1568		/// If a user encounters the `InsufficientBond` error when calling this extrinsic,
1569		/// they should call `chill` first in order to free up their bonded funds.
1570		///
1571		/// Emits `Unbonded`.
1572		///
1573		/// See also [`Call::withdraw_unbonded`].
1574		#[pallet::call_index(2)]
1575		#[pallet::weight(
1576            T::WeightInfo::withdraw_unbonded_kill().saturating_add(T::WeightInfo::unbond()))
1577        ]
1578		pub fn unbond(
1579			origin: OriginFor<T>,
1580			#[pallet::compact] value: BalanceOf<T>,
1581		) -> DispatchResultWithPostInfo {
1582			let controller = ensure_signed(origin)?;
1583			let unlocking =
1584				Self::ledger(Controller(controller.clone())).map(|l| l.unlocking.len())?;
1585
1586			// if there are no unlocking chunks available, try to remove any chunks by withdrawing
1587			// funds that have fully unbonded.
1588			let maybe_withdraw_weight = {
1589				if unlocking == T::MaxUnlockingChunks::get() as usize {
1590					Some(Self::do_withdraw_unbonded(&controller)?)
1591				} else {
1592					None
1593				}
1594			};
1595
1596			// we need to fetch the ledger again because it may have been mutated in the call
1597			// to `Self::do_withdraw_unbonded` above.
1598			let mut ledger = Self::ledger(Controller(controller))?;
1599			let mut value = value.min(ledger.active);
1600			let stash = ledger.stash.clone();
1601
1602			ensure!(
1603				ledger.unlocking.len() < T::MaxUnlockingChunks::get() as usize,
1604				Error::<T>::NoMoreChunks,
1605			);
1606
1607			if !value.is_zero() {
1608				ledger.active -= value;
1609
1610				// Avoid there being a dust balance left in the staking system.
1611				if ledger.active < asset::existential_deposit::<T>() {
1612					value += ledger.active;
1613					ledger.active = Zero::zero();
1614				}
1615
1616				let min_active_bond = if Nominators::<T>::contains_key(&stash) {
1617					Self::min_nominator_bond()
1618				} else if Validators::<T>::contains_key(&stash) {
1619					Self::min_validator_bond()
1620				} else {
1621					// staker is chilled, no min bond.
1622					Zero::zero()
1623				};
1624
1625				// Make sure that the user maintains enough active bond for their role.
1626				// If a user runs into this error, they should chill first.
1627				ensure!(ledger.active >= min_active_bond, Error::<T>::InsufficientBond);
1628
1629				// Note: we used current era before, but that is meant to be used for only election.
1630				// The right value to use here is the active era.
1631
1632				let era = session_rotation::Rotator::<T>::active_era()
1633					.saturating_add(T::BondingDuration::get());
1634				if let Some(chunk) = ledger.unlocking.last_mut().filter(|chunk| chunk.era == era) {
1635					// To keep the chunk count down, we only keep one chunk per era. Since
1636					// `unlocking` is a FiFo queue, if a chunk exists for `era` we know that it will
1637					// be the last one.
1638					chunk.value = chunk.value.defensive_saturating_add(value)
1639				} else {
1640					ledger
1641						.unlocking
1642						.try_push(UnlockChunk { value, era })
1643						.map_err(|_| Error::<T>::NoMoreChunks)?;
1644				};
1645				// NOTE: ledger must be updated prior to calling `Self::weight_of`.
1646				ledger.update()?;
1647
1648				// update this staker in the sorted list, if they exist in it.
1649				if T::VoterList::contains(&stash) {
1650					let _ = T::VoterList::on_update(&stash, Self::weight_of(&stash));
1651				}
1652
1653				Self::deposit_event(Event::<T>::Unbonded { stash, amount: value });
1654			}
1655
1656			let actual_weight = if let Some(withdraw_weight) = maybe_withdraw_weight {
1657				Some(T::WeightInfo::unbond().saturating_add(withdraw_weight))
1658			} else {
1659				Some(T::WeightInfo::unbond())
1660			};
1661
1662			Ok(actual_weight.into())
1663		}
1664
1665		/// Remove any stake that has been fully unbonded and is ready for withdrawal.
1666		///
1667		/// Stake is considered fully unbonded once [`Config::BondingDuration`] has elapsed since
1668		/// the unbonding was initiated. In rare cases—such as when offences for the unbonded era
1669		/// have been reported but not yet processed—withdrawal is restricted to eras for which
1670		/// all offences have been processed.
1671		///
1672		/// The unlocked stake will be returned as free balance in the stash account.
1673		///
1674		/// The dispatch origin for this call must be _Signed_ by the controller.
1675		///
1676		/// Emits `Withdrawn`.
1677		///
1678		/// See also [`Call::unbond`].
1679		///
1680		/// ## Parameters
1681		///
1682		/// - `num_slashing_spans`: **Deprecated**. Retained only for backward compatibility; this
1683		///   parameter has no effect.
1684		#[pallet::call_index(3)]
1685		#[pallet::weight(T::WeightInfo::withdraw_unbonded_kill())]
1686		pub fn withdraw_unbonded(
1687			origin: OriginFor<T>,
1688			_num_slashing_spans: u32,
1689		) -> DispatchResultWithPostInfo {
1690			let controller = ensure_signed(origin)?;
1691
1692			let actual_weight = Self::do_withdraw_unbonded(&controller)?;
1693			Ok(Some(actual_weight).into())
1694		}
1695
1696		/// Declare the desire to validate for the origin controller.
1697		///
1698		/// Effects will be felt at the beginning of the next era.
1699		///
1700		/// The dispatch origin for this call must be _Signed_ by the controller, not the stash.
1701		#[pallet::call_index(4)]
1702		#[pallet::weight(T::WeightInfo::validate())]
1703		pub fn validate(origin: OriginFor<T>, prefs: ValidatorPrefs) -> DispatchResult {
1704			let controller = ensure_signed(origin)?;
1705
1706			let ledger = Self::ledger(Controller(controller))?;
1707
1708			ensure!(ledger.active >= Self::min_validator_bond(), Error::<T>::InsufficientBond);
1709			let stash = &ledger.stash;
1710
1711			// ensure their commission is correct.
1712			ensure!(prefs.commission >= MinCommission::<T>::get(), Error::<T>::CommissionTooLow);
1713
1714			// Only check limits if they are not already a validator.
1715			if !Validators::<T>::contains_key(stash) {
1716				// If this error is reached, we need to adjust the `MinValidatorBond` and start
1717				// calling `chill_other`. Until then, we explicitly block new validators to protect
1718				// the runtime.
1719				if let Some(max_validators) = MaxValidatorsCount::<T>::get() {
1720					ensure!(
1721						Validators::<T>::count() < max_validators,
1722						Error::<T>::TooManyValidators
1723					);
1724				}
1725			}
1726
1727			Self::do_remove_nominator(stash);
1728			Self::do_add_validator(stash, prefs.clone());
1729			Self::deposit_event(Event::<T>::ValidatorPrefsSet { stash: ledger.stash, prefs });
1730
1731			Ok(())
1732		}
1733
1734		/// Declare the desire to nominate `targets` for the origin controller.
1735		///
1736		/// Effects will be felt at the beginning of the next era.
1737		///
1738		/// The dispatch origin for this call must be _Signed_ by the controller, not the stash.
1739		#[pallet::call_index(5)]
1740		#[pallet::weight(T::WeightInfo::nominate(targets.len() as u32))]
1741		pub fn nominate(
1742			origin: OriginFor<T>,
1743			targets: Vec<AccountIdLookupOf<T>>,
1744		) -> DispatchResult {
1745			let controller = ensure_signed(origin)?;
1746
1747			let ledger = Self::ledger(StakingAccount::Controller(controller.clone()))?;
1748
1749			ensure!(ledger.active >= Self::min_nominator_bond(), Error::<T>::InsufficientBond);
1750			let stash = &ledger.stash;
1751
1752			// Only check limits if they are not already a nominator.
1753			if !Nominators::<T>::contains_key(stash) {
1754				// If this error is reached, we need to adjust the `MinNominatorBond` and start
1755				// calling `chill_other`. Until then, we explicitly block new nominators to protect
1756				// the runtime.
1757				if let Some(max_nominators) = MaxNominatorsCount::<T>::get() {
1758					ensure!(
1759						Nominators::<T>::count() < max_nominators,
1760						Error::<T>::TooManyNominators
1761					);
1762				}
1763			}
1764
1765			// dedup targets
1766			let mut targets = targets
1767				.into_iter()
1768				.map(|t| T::Lookup::lookup(t).map_err(DispatchError::from))
1769				.collect::<Result<Vec<_>, _>>()?;
1770			targets.sort();
1771			targets.dedup();
1772
1773			ensure!(!targets.is_empty(), Error::<T>::EmptyTargets);
1774			ensure!(
1775				targets.len() <= T::NominationsQuota::get_quota(ledger.active) as usize,
1776				Error::<T>::TooManyTargets
1777			);
1778
1779			let old = Nominators::<T>::get(stash).map_or_else(Vec::new, |x| x.targets.into_inner());
1780
1781			let targets: BoundedVec<_, _> = targets
1782				.into_iter()
1783				.map(|n| {
1784					if old.contains(&n) ||
1785						(Validators::<T>::contains_key(&n) && !Validators::<T>::get(&n).blocked)
1786					{
1787						Ok(n)
1788					} else {
1789						Err(Error::<T>::BadTarget.into())
1790					}
1791				})
1792				.collect::<Result<Vec<_>, DispatchError>>()?
1793				.try_into()
1794				.map_err(|_| Error::<T>::TooManyNominators)?;
1795
1796			let nominations = Nominations {
1797				targets,
1798				// Initial nominations are considered submitted at era 0. See `Nominations` doc.
1799				submitted_in: CurrentEra::<T>::get().unwrap_or(0),
1800				suppressed: false,
1801			};
1802
1803			Self::do_remove_validator(stash);
1804			Self::do_add_nominator(stash, nominations);
1805			Ok(())
1806		}
1807
1808		/// Declare no desire to either validate or nominate.
1809		///
1810		/// Effects will be felt at the beginning of the next era.
1811		///
1812		/// The dispatch origin for this call must be _Signed_ by the controller, not the stash.
1813		///
1814		/// ## Complexity
1815		/// - Independent of the arguments. Insignificant complexity.
1816		/// - Contains one read.
1817		/// - Writes are limited to the `origin` account key.
1818		#[pallet::call_index(6)]
1819		#[pallet::weight(T::WeightInfo::chill())]
1820		pub fn chill(origin: OriginFor<T>) -> DispatchResult {
1821			let controller = ensure_signed(origin)?;
1822
1823			let ledger = Self::ledger(StakingAccount::Controller(controller))?;
1824
1825			Self::chill_stash(&ledger.stash);
1826			Ok(())
1827		}
1828
1829		/// (Re-)set the payment target for a controller.
1830		///
1831		/// Effects will be felt instantly (as soon as this function is completed successfully).
1832		///
1833		/// The dispatch origin for this call must be _Signed_ by the controller, not the stash.
1834		#[pallet::call_index(7)]
1835		#[pallet::weight(T::WeightInfo::set_payee())]
1836		pub fn set_payee(
1837			origin: OriginFor<T>,
1838			payee: RewardDestination<T::AccountId>,
1839		) -> DispatchResult {
1840			let controller = ensure_signed(origin)?;
1841			let ledger = Self::ledger(Controller(controller.clone()))?;
1842
1843			ensure!(
1844				(payee != {
1845					#[allow(deprecated)]
1846					RewardDestination::Controller
1847				}),
1848				Error::<T>::ControllerDeprecated
1849			);
1850
1851			let _ = ledger
1852				.set_payee(payee)
1853				.defensive_proof("ledger was retrieved from storage, thus it's bonded; qed.")?;
1854
1855			Ok(())
1856		}
1857
1858		/// (Re-)sets the controller of a stash to the stash itself. This function previously
1859		/// accepted a `controller` argument to set the controller to an account other than the
1860		/// stash itself. This functionality has now been removed, now only setting the controller
1861		/// to the stash, if it is not already.
1862		///
1863		/// Effects will be felt instantly (as soon as this function is completed successfully).
1864		///
1865		/// The dispatch origin for this call must be _Signed_ by the stash, not the controller.
1866		#[pallet::call_index(8)]
1867		#[pallet::weight(T::WeightInfo::set_controller())]
1868		pub fn set_controller(origin: OriginFor<T>) -> DispatchResult {
1869			let stash = ensure_signed(origin)?;
1870
1871			Self::ledger(StakingAccount::Stash(stash.clone())).map(|ledger| {
1872				let controller = ledger.controller()
1873                    .defensive_proof("Ledger's controller field didn't exist. The controller should have been fetched using StakingLedger.")
1874                    .ok_or(Error::<T>::NotController)?;
1875
1876				if controller == stash {
1877					// Stash is already its own controller.
1878					return Err(Error::<T>::AlreadyPaired.into())
1879				}
1880
1881				let _ = ledger.set_controller_to_stash()?;
1882				Ok(())
1883			})?
1884		}
1885
1886		/// Sets the ideal number of validators.
1887		///
1888		/// The dispatch origin must be Root.
1889		#[pallet::call_index(9)]
1890		#[pallet::weight(T::WeightInfo::set_validator_count())]
1891		pub fn set_validator_count(
1892			origin: OriginFor<T>,
1893			#[pallet::compact] new: u32,
1894		) -> DispatchResult {
1895			ensure_root(origin)?;
1896
1897			ensure!(new <= T::MaxValidatorSet::get(), Error::<T>::TooManyValidators);
1898
1899			ValidatorCount::<T>::put(new);
1900			Ok(())
1901		}
1902
1903		/// Increments the ideal number of validators up to maximum of
1904		/// `T::MaxValidatorSet`.
1905		///
1906		/// The dispatch origin must be Root.
1907		#[pallet::call_index(10)]
1908		#[pallet::weight(T::WeightInfo::set_validator_count())]
1909		pub fn increase_validator_count(
1910			origin: OriginFor<T>,
1911			#[pallet::compact] additional: u32,
1912		) -> DispatchResult {
1913			ensure_root(origin)?;
1914			let old = ValidatorCount::<T>::get();
1915			let new = old.checked_add(additional).ok_or(ArithmeticError::Overflow)?;
1916
1917			ensure!(new <= T::MaxValidatorSet::get(), Error::<T>::TooManyValidators);
1918
1919			ValidatorCount::<T>::put(new);
1920			Ok(())
1921		}
1922
1923		/// Scale up the ideal number of validators by a factor up to maximum of
1924		/// `T::MaxValidatorSet`.
1925		///
1926		/// The dispatch origin must be Root.
1927		#[pallet::call_index(11)]
1928		#[pallet::weight(T::WeightInfo::set_validator_count())]
1929		pub fn scale_validator_count(origin: OriginFor<T>, factor: Percent) -> DispatchResult {
1930			ensure_root(origin)?;
1931			let old = ValidatorCount::<T>::get();
1932			let new = old.checked_add(factor.mul_floor(old)).ok_or(ArithmeticError::Overflow)?;
1933
1934			ensure!(new <= T::MaxValidatorSet::get(), Error::<T>::TooManyValidators);
1935
1936			ValidatorCount::<T>::put(new);
1937			Ok(())
1938		}
1939
1940		/// Force there to be no new eras indefinitely.
1941		///
1942		/// The dispatch origin must be Root.
1943		///
1944		/// # Warning
1945		///
1946		/// The election process starts multiple blocks before the end of the era.
1947		/// Thus the election process may be ongoing when this is called. In this case the
1948		/// election will continue until the next era is triggered.
1949		#[pallet::call_index(12)]
1950		#[pallet::weight(T::WeightInfo::force_no_eras())]
1951		pub fn force_no_eras(origin: OriginFor<T>) -> DispatchResult {
1952			ensure_root(origin)?;
1953			Self::set_force_era(Forcing::ForceNone);
1954			Ok(())
1955		}
1956
1957		/// Force there to be a new era at the end of the next session. After this, it will be
1958		/// reset to normal (non-forced) behaviour.
1959		///
1960		/// The dispatch origin must be Root.
1961		///
1962		/// # Warning
1963		///
1964		/// The election process starts multiple blocks before the end of the era.
1965		/// If this is called just before a new era is triggered, the election process may not
1966		/// have enough blocks to get a result.
1967		#[pallet::call_index(13)]
1968		#[pallet::weight(T::WeightInfo::force_new_era())]
1969		pub fn force_new_era(origin: OriginFor<T>) -> DispatchResult {
1970			ensure_root(origin)?;
1971			Self::set_force_era(Forcing::ForceNew);
1972			Ok(())
1973		}
1974
1975		/// Force a current staker to become completely unstaked, immediately.
1976		///
1977		/// The dispatch origin must be Root.
1978		/// ## Parameters
1979		///
1980		/// - `stash`: The stash account to be unstaked.
1981		/// - `num_slashing_spans`: **Deprecated**. This parameter is retained for backward
1982		/// compatibility. It no longer has any effect.
1983		#[pallet::call_index(15)]
1984		#[pallet::weight(T::WeightInfo::force_unstake())]
1985		pub fn force_unstake(
1986			origin: OriginFor<T>,
1987			stash: T::AccountId,
1988			_num_slashing_spans: u32,
1989		) -> DispatchResult {
1990			ensure_root(origin)?;
1991
1992			// Remove all staking-related information and lock.
1993			Self::kill_stash(&stash)?;
1994
1995			Ok(())
1996		}
1997
1998		/// Force there to be a new era at the end of sessions indefinitely.
1999		///
2000		/// The dispatch origin must be Root.
2001		///
2002		/// # Warning
2003		///
2004		/// The election process starts multiple blocks before the end of the era.
2005		/// If this is called just before a new era is triggered, the election process may not
2006		/// have enough blocks to get a result.
2007		#[pallet::call_index(16)]
2008		#[pallet::weight(T::WeightInfo::force_new_era_always())]
2009		pub fn force_new_era_always(origin: OriginFor<T>) -> DispatchResult {
2010			ensure_root(origin)?;
2011			Self::set_force_era(Forcing::ForceAlways);
2012			Ok(())
2013		}
2014
2015		/// Cancels scheduled slashes for a given era before they are applied.
2016		///
2017		/// This function allows `T::AdminOrigin` to cancel pending slashes for specified validators
2018		/// in a given era. The cancelled slashes are stored and will be checked when applying
2019		/// slashes.
2020		///
2021		/// ## Parameters
2022		/// - `era`: The staking era for which slashes should be cancelled. This is the era where
2023		///   the slash would be applied, not the era in which the offence was committed.
2024		/// - `validator_slashes`: A list of validator stash accounts and their slash fractions to
2025		///   be cancelled.
2026		#[pallet::call_index(17)]
2027		#[pallet::weight(T::WeightInfo::cancel_deferred_slash(validator_slashes.len() as u32))]
2028		pub fn cancel_deferred_slash(
2029			origin: OriginFor<T>,
2030			era: EraIndex,
2031			validator_slashes: Vec<(T::AccountId, Perbill)>,
2032		) -> DispatchResult {
2033			T::AdminOrigin::ensure_origin(origin)?;
2034			ensure!(!validator_slashes.is_empty(), Error::<T>::EmptyTargets);
2035
2036			// Get current cancelled slashes for this era
2037			let mut cancelled_slashes = CancelledSlashes::<T>::get(&era);
2038
2039			// Process each validator slash
2040			for (validator, slash_fraction) in validator_slashes {
2041				// Since this is gated by admin origin, we don't need to check if they are really
2042				// validators and trust governance to correctly set the parameters.
2043
2044				// Remove any existing entry for this validator
2045				cancelled_slashes.retain(|(v, _)| v != &validator);
2046
2047				// Add the validator with the specified slash fraction
2048				cancelled_slashes
2049					.try_push((validator.clone(), slash_fraction))
2050					.map_err(|_| Error::<T>::BoundNotMet)
2051					.defensive_proof("cancelled_slashes should have capacity for all validators")?;
2052
2053				Self::deposit_event(Event::<T>::SlashCancelled { slash_era: era, validator });
2054			}
2055
2056			// Update storage
2057			CancelledSlashes::<T>::insert(&era, cancelled_slashes);
2058
2059			Ok(())
2060		}
2061
2062		/// Pay out next page of the stakers behind a validator for the given era.
2063		///
2064		/// - `validator_stash` is the stash account of the validator.
2065		/// - `era` may be any era between `[current_era - history_depth; current_era]`.
2066		///
2067		/// The origin of this call must be _Signed_. Any account can call this function, even if
2068		/// it is not one of the stakers.
2069		///
2070		/// The reward payout could be paged in case there are too many nominators backing the
2071		/// `validator_stash`. This call will payout unpaid pages in an ascending order. To claim a
2072		/// specific page, use `payout_stakers_by_page`.`
2073		///
2074		/// If all pages are claimed, it returns an error `InvalidPage`.
2075		#[pallet::call_index(18)]
2076		#[pallet::weight(T::WeightInfo::payout_stakers_alive_staked(T::MaxExposurePageSize::get()))]
2077		pub fn payout_stakers(
2078			origin: OriginFor<T>,
2079			validator_stash: T::AccountId,
2080			era: EraIndex,
2081		) -> DispatchResultWithPostInfo {
2082			ensure_signed(origin)?;
2083
2084			Self::do_payout_stakers(validator_stash, era)
2085		}
2086
2087		/// Rebond a portion of the stash scheduled to be unlocked.
2088		///
2089		/// The dispatch origin must be signed by the controller.
2090		#[pallet::call_index(19)]
2091		#[pallet::weight(T::WeightInfo::rebond(T::MaxUnlockingChunks::get() as u32))]
2092		pub fn rebond(
2093			origin: OriginFor<T>,
2094			#[pallet::compact] value: BalanceOf<T>,
2095		) -> DispatchResultWithPostInfo {
2096			let controller = ensure_signed(origin)?;
2097			let ledger = Self::ledger(Controller(controller))?;
2098
2099			ensure!(!T::Filter::contains(&ledger.stash), Error::<T>::Restricted);
2100			ensure!(!ledger.unlocking.is_empty(), Error::<T>::NoUnlockChunk);
2101
2102			let initial_unlocking = ledger.unlocking.len() as u32;
2103			let (ledger, rebonded_value) = ledger.rebond(value);
2104			// Last check: the new active amount of ledger must be more than min bond.
2105			ensure!(ledger.active >= Self::min_chilled_bond(), Error::<T>::InsufficientBond);
2106
2107			Self::deposit_event(Event::<T>::Bonded {
2108				stash: ledger.stash.clone(),
2109				amount: rebonded_value,
2110			});
2111
2112			let stash = ledger.stash.clone();
2113			let final_unlocking = ledger.unlocking.len();
2114
2115			// NOTE: ledger must be updated prior to calling `Self::weight_of`.
2116			ledger.update()?;
2117			if T::VoterList::contains(&stash) {
2118				let _ = T::VoterList::on_update(&stash, Self::weight_of(&stash));
2119			}
2120
2121			let removed_chunks = 1u32 // for the case where the last iterated chunk is not removed
2122				.saturating_add(initial_unlocking)
2123				.saturating_sub(final_unlocking as u32);
2124			Ok(Some(T::WeightInfo::rebond(removed_chunks)).into())
2125		}
2126
2127		/// Remove all data structures concerning a staker/stash once it is at a state where it can
2128		/// be considered `dust` in the staking system. The requirements are:
2129		///
2130		/// 1. the `total_balance` of the stash is below `min_chilled_bond` or is zero.
2131		/// 2. or, the `ledger.total` of the stash is below `min_chilled_bond` or is zero.
2132		///
2133		/// The former can happen in cases like a slash; the latter when a fully unbonded account
2134		/// is still receiving staking rewards in `RewardDestination::Staked`.
2135		///
2136		/// It can be called by anyone, as long as `stash` meets the above requirements.
2137		///
2138		/// Refunds the transaction fees upon successful execution.
2139		///
2140		/// ## Parameters
2141		///
2142		/// - `stash`: The stash account to be reaped.
2143		/// - `num_slashing_spans`: **Deprecated**. This parameter is retained for backward
2144		/// compatibility. It no longer has any effect.
2145		#[pallet::call_index(20)]
2146		#[pallet::weight(T::WeightInfo::reap_stash())]
2147		pub fn reap_stash(
2148			origin: OriginFor<T>,
2149			stash: T::AccountId,
2150			_num_slashing_spans: u32,
2151		) -> DispatchResultWithPostInfo {
2152			let _ = ensure_signed(origin)?;
2153
2154			// virtual stakers should not be allowed to be reaped.
2155			ensure!(!Self::is_virtual_staker(&stash), Error::<T>::VirtualStakerNotAllowed);
2156
2157			let min_chilled_bond = Self::min_chilled_bond();
2158			let origin_balance = asset::total_balance::<T>(&stash);
2159			let ledger_total =
2160				Self::ledger(Stash(stash.clone())).map(|l| l.total).unwrap_or_default();
2161			let reapable = origin_balance < min_chilled_bond ||
2162				origin_balance.is_zero() ||
2163				ledger_total < min_chilled_bond ||
2164				ledger_total.is_zero();
2165			ensure!(reapable, Error::<T>::FundedTarget);
2166
2167			// Remove all staking-related information and lock.
2168			Self::kill_stash(&stash)?;
2169
2170			Ok(Pays::No.into())
2171		}
2172
2173		/// Remove the given nominations from the calling validator.
2174		///
2175		/// Effects will be felt at the beginning of the next era.
2176		///
2177		/// The dispatch origin for this call must be _Signed_ by the controller, not the stash.
2178		///
2179		/// - `who`: A list of nominator stash accounts who are nominating this validator which
2180		///   should no longer be nominating this validator.
2181		///
2182		/// Note: Making this call only makes sense if you first set the validator preferences to
2183		/// block any further nominations.
2184		#[pallet::call_index(21)]
2185		#[pallet::weight(T::WeightInfo::kick(who.len() as u32))]
2186		pub fn kick(origin: OriginFor<T>, who: Vec<AccountIdLookupOf<T>>) -> DispatchResult {
2187			let controller = ensure_signed(origin)?;
2188			let ledger = Self::ledger(Controller(controller))?;
2189			let stash = &ledger.stash;
2190
2191			for nom_stash in who
2192				.into_iter()
2193				.map(T::Lookup::lookup)
2194				.collect::<Result<Vec<T::AccountId>, _>>()?
2195				.into_iter()
2196			{
2197				Nominators::<T>::mutate(&nom_stash, |maybe_nom| {
2198					if let Some(ref mut nom) = maybe_nom {
2199						if let Some(pos) = nom.targets.iter().position(|v| v == stash) {
2200							nom.targets.swap_remove(pos);
2201							Self::deposit_event(Event::<T>::Kicked {
2202								nominator: nom_stash.clone(),
2203								stash: stash.clone(),
2204							});
2205						}
2206					}
2207				});
2208			}
2209
2210			Ok(())
2211		}
2212
2213		/// Update the various staking configurations .
2214		///
2215		/// * `min_nominator_bond`: The minimum active bond needed to be a nominator.
2216		/// * `min_validator_bond`: The minimum active bond needed to be a validator.
2217		/// * `max_nominator_count`: The max number of users who can be a nominator at once. When
2218		///   set to `None`, no limit is enforced.
2219		/// * `max_validator_count`: The max number of users who can be a validator at once. When
2220		///   set to `None`, no limit is enforced.
2221		/// * `chill_threshold`: The ratio of `max_nominator_count` or `max_validator_count` which
2222		///   should be filled in order for the `chill_other` transaction to work.
2223		/// * `min_commission`: The minimum amount of commission that each validators must maintain.
2224		///   This is checked only upon calling `validate`. Existing validators are not affected.
2225		///
2226		/// RuntimeOrigin must be Root to call this function.
2227		///
2228		/// NOTE: Existing nominators and validators will not be affected by this update.
2229		/// to kick people under the new limits, `chill_other` should be called.
2230		// We assume the worst case for this call is either: all items are set or all items are
2231		// removed.
2232		#[pallet::call_index(22)]
2233		#[pallet::weight(
2234			T::WeightInfo::set_staking_configs_all_set()
2235				.max(T::WeightInfo::set_staking_configs_all_remove())
2236		)]
2237		pub fn set_staking_configs(
2238			origin: OriginFor<T>,
2239			min_nominator_bond: ConfigOp<BalanceOf<T>>,
2240			min_validator_bond: ConfigOp<BalanceOf<T>>,
2241			max_nominator_count: ConfigOp<u32>,
2242			max_validator_count: ConfigOp<u32>,
2243			chill_threshold: ConfigOp<Percent>,
2244			min_commission: ConfigOp<Perbill>,
2245			max_staked_rewards: ConfigOp<Percent>,
2246		) -> DispatchResult {
2247			ensure_root(origin)?;
2248
2249			macro_rules! config_op_exp {
2250				($storage:ty, $op:ident) => {
2251					match $op {
2252						ConfigOp::Noop => (),
2253						ConfigOp::Set(v) => <$storage>::put(v),
2254						ConfigOp::Remove => <$storage>::kill(),
2255					}
2256				};
2257			}
2258
2259			config_op_exp!(MinNominatorBond<T>, min_nominator_bond);
2260			config_op_exp!(MinValidatorBond<T>, min_validator_bond);
2261			config_op_exp!(MaxNominatorsCount<T>, max_nominator_count);
2262			config_op_exp!(MaxValidatorsCount<T>, max_validator_count);
2263			config_op_exp!(ChillThreshold<T>, chill_threshold);
2264			config_op_exp!(MinCommission<T>, min_commission);
2265			config_op_exp!(MaxStakedRewards<T>, max_staked_rewards);
2266			Ok(())
2267		}
2268		/// Declare a `controller` to stop participating as either a validator or nominator.
2269		///
2270		/// Effects will be felt at the beginning of the next era.
2271		///
2272		/// The dispatch origin for this call must be _Signed_, but can be called by anyone.
2273		///
2274		/// If the caller is the same as the controller being targeted, then no further checks are
2275		/// enforced, and this function behaves just like `chill`.
2276		///
2277		/// If the caller is different than the controller being targeted, the following conditions
2278		/// must be met:
2279		///
2280		/// * `controller` must belong to a nominator who has become non-decodable,
2281		///
2282		/// Or:
2283		///
2284		/// * A `ChillThreshold` must be set and checked which defines how close to the max
2285		///   nominators or validators we must reach before users can start chilling one-another.
2286		/// * A `MaxNominatorCount` and `MaxValidatorCount` must be set which is used to determine
2287		///   how close we are to the threshold.
2288		/// * A `MinNominatorBond` and `MinValidatorBond` must be set and checked, which determines
2289		///   if this is a person that should be chilled because they have not met the threshold
2290		///   bond required.
2291		///
2292		/// This can be helpful if bond requirements are updated, and we need to remove old users
2293		/// who do not satisfy these requirements.
2294		#[pallet::call_index(23)]
2295		#[pallet::weight(T::WeightInfo::chill_other())]
2296		pub fn chill_other(origin: OriginFor<T>, stash: T::AccountId) -> DispatchResult {
2297			// Anyone can call this function.
2298			let caller = ensure_signed(origin)?;
2299			let ledger = Self::ledger(Stash(stash.clone()))?;
2300			let controller = ledger
2301				.controller()
2302				.defensive_proof(
2303					"Ledger's controller field didn't exist. The controller should have been fetched using StakingLedger.",
2304				)
2305				.ok_or(Error::<T>::NotController)?;
2306
2307			// In order for one user to chill another user, the following conditions must be met:
2308			//
2309			// * `controller` belongs to a nominator who has become non-decodable,
2310			//
2311			// Or
2312			//
2313			// * A `ChillThreshold` is set which defines how close to the max nominators or
2314			//   validators we must reach before users can start chilling one-another.
2315			// * A `MaxNominatorCount` and `MaxValidatorCount` which is used to determine how close
2316			//   we are to the threshold.
2317			// * A `MinNominatorBond` and `MinValidatorBond` which is the final condition checked to
2318			//   determine this is a person that should be chilled because they have not met the
2319			//   threshold bond required.
2320			//
2321			// Otherwise, if caller is the same as the controller, this is just like `chill`.
2322
2323			if Nominators::<T>::contains_key(&stash) && Nominators::<T>::get(&stash).is_none() {
2324				Self::chill_stash(&stash);
2325				return Ok(());
2326			}
2327
2328			if caller != controller {
2329				let threshold = ChillThreshold::<T>::get().ok_or(Error::<T>::CannotChillOther)?;
2330				let min_active_bond = if Nominators::<T>::contains_key(&stash) {
2331					let max_nominator_count =
2332						MaxNominatorsCount::<T>::get().ok_or(Error::<T>::CannotChillOther)?;
2333					let current_nominator_count = Nominators::<T>::count();
2334					ensure!(
2335						threshold * max_nominator_count < current_nominator_count,
2336						Error::<T>::CannotChillOther
2337					);
2338					Self::min_nominator_bond()
2339				} else if Validators::<T>::contains_key(&stash) {
2340					let max_validator_count =
2341						MaxValidatorsCount::<T>::get().ok_or(Error::<T>::CannotChillOther)?;
2342					let current_validator_count = Validators::<T>::count();
2343					ensure!(
2344						threshold * max_validator_count < current_validator_count,
2345						Error::<T>::CannotChillOther
2346					);
2347					Self::min_validator_bond()
2348				} else {
2349					Zero::zero()
2350				};
2351
2352				ensure!(ledger.active < min_active_bond, Error::<T>::CannotChillOther);
2353			}
2354
2355			Self::chill_stash(&stash);
2356			Ok(())
2357		}
2358
2359		/// Force a validator to have at least the minimum commission. This will not affect a
2360		/// validator who already has a commission greater than or equal to the minimum. Any account
2361		/// can call this.
2362		#[pallet::call_index(24)]
2363		#[pallet::weight(T::WeightInfo::force_apply_min_commission())]
2364		pub fn force_apply_min_commission(
2365			origin: OriginFor<T>,
2366			validator_stash: T::AccountId,
2367		) -> DispatchResult {
2368			ensure_signed(origin)?;
2369			let min_commission = MinCommission::<T>::get();
2370			Validators::<T>::try_mutate_exists(validator_stash, |maybe_prefs| {
2371				maybe_prefs
2372					.as_mut()
2373					.map(|prefs| {
2374						(prefs.commission < min_commission)
2375							.then(|| prefs.commission = min_commission)
2376					})
2377					.ok_or(Error::<T>::NotStash)
2378			})?;
2379			Ok(())
2380		}
2381
2382		/// Sets the minimum amount of commission that each validators must maintain.
2383		///
2384		/// This call has lower privilege requirements than `set_staking_config` and can be called
2385		/// by the `T::AdminOrigin`. Root can always call this.
2386		#[pallet::call_index(25)]
2387		#[pallet::weight(T::WeightInfo::set_min_commission())]
2388		pub fn set_min_commission(origin: OriginFor<T>, new: Perbill) -> DispatchResult {
2389			T::AdminOrigin::ensure_origin(origin)?;
2390			MinCommission::<T>::put(new);
2391			Ok(())
2392		}
2393
2394		/// Pay out a page of the stakers behind a validator for the given era and page.
2395		///
2396		/// - `validator_stash` is the stash account of the validator.
2397		/// - `era` may be any era between `[current_era - history_depth; current_era]`.
2398		/// - `page` is the page index of nominators to pay out with value between 0 and
2399		///   `num_nominators / T::MaxExposurePageSize`.
2400		///
2401		/// The origin of this call must be _Signed_. Any account can call this function, even if
2402		/// it is not one of the stakers.
2403		///
2404		/// If a validator has more than [`Config::MaxExposurePageSize`] nominators backing
2405		/// them, then the list of nominators is paged, with each page being capped at
2406		/// [`Config::MaxExposurePageSize`.] If a validator has more than one page of nominators,
2407		/// the call needs to be made for each page separately in order for all the nominators
2408		/// backing a validator to receive the reward. The nominators are not sorted across pages
2409		/// and so it should not be assumed the highest staker would be on the topmost page and vice
2410		/// versa. If rewards are not claimed in [`Config::HistoryDepth`] eras, they are lost.
2411		#[pallet::call_index(26)]
2412		#[pallet::weight(T::WeightInfo::payout_stakers_alive_staked(T::MaxExposurePageSize::get()))]
2413		pub fn payout_stakers_by_page(
2414			origin: OriginFor<T>,
2415			validator_stash: T::AccountId,
2416			era: EraIndex,
2417			page: Page,
2418		) -> DispatchResultWithPostInfo {
2419			ensure_signed(origin)?;
2420			Self::do_payout_stakers_by_page(validator_stash, era, page)
2421		}
2422
2423		/// Migrates an account's `RewardDestination::Controller` to
2424		/// `RewardDestination::Account(controller)`.
2425		///
2426		/// Effects will be felt instantly (as soon as this function is completed successfully).
2427		///
2428		/// This will waive the transaction fee if the `payee` is successfully migrated.
2429		#[pallet::call_index(27)]
2430		#[pallet::weight(T::WeightInfo::update_payee())]
2431		pub fn update_payee(
2432			origin: OriginFor<T>,
2433			controller: T::AccountId,
2434		) -> DispatchResultWithPostInfo {
2435			let _ = ensure_signed(origin)?;
2436			let ledger = Self::ledger(StakingAccount::Controller(controller.clone()))?;
2437
2438			ensure!(
2439				(Payee::<T>::get(&ledger.stash) == {
2440					#[allow(deprecated)]
2441					Some(RewardDestination::Controller)
2442				}),
2443				Error::<T>::NotController
2444			);
2445
2446			let _ = ledger
2447				.set_payee(RewardDestination::Account(controller))
2448				.defensive_proof("ledger should have been previously retrieved from storage.")?;
2449
2450			Ok(Pays::No.into())
2451		}
2452
2453		/// Updates a batch of controller accounts to their corresponding stash account if they are
2454		/// not the same. Ignores any controller accounts that do not exist, and does not operate if
2455		/// the stash and controller are already the same.
2456		///
2457		/// Effects will be felt instantly (as soon as this function is completed successfully).
2458		///
2459		/// The dispatch origin must be `T::AdminOrigin`.
2460		#[pallet::call_index(28)]
2461		#[pallet::weight(T::WeightInfo::deprecate_controller_batch(controllers.len() as u32))]
2462		pub fn deprecate_controller_batch(
2463			origin: OriginFor<T>,
2464			controllers: BoundedVec<T::AccountId, T::MaxControllersInDeprecationBatch>,
2465		) -> DispatchResultWithPostInfo {
2466			T::AdminOrigin::ensure_origin(origin)?;
2467
2468			// Ignore controllers that do not exist or are already the same as stash.
2469			let filtered_batch_with_ledger: Vec<_> = controllers
2470				.iter()
2471				.filter_map(|controller| {
2472					let ledger = Self::ledger(StakingAccount::Controller(controller.clone()));
2473					ledger.ok().map_or(None, |ledger| {
2474						// If the controller `RewardDestination` is still the deprecated
2475						// `Controller` variant, skip deprecating this account.
2476						let payee_deprecated = Payee::<T>::get(&ledger.stash) == {
2477							#[allow(deprecated)]
2478							Some(RewardDestination::Controller)
2479						};
2480
2481						if ledger.stash != *controller && !payee_deprecated {
2482							Some(ledger)
2483						} else {
2484							None
2485						}
2486					})
2487				})
2488				.collect();
2489
2490			// Update unique pairs.
2491			let mut failures = 0;
2492			for ledger in filtered_batch_with_ledger {
2493				let _ = ledger.clone().set_controller_to_stash().map_err(|_| failures += 1);
2494			}
2495			Self::deposit_event(Event::<T>::ControllerBatchDeprecated { failures });
2496
2497			Ok(Some(T::WeightInfo::deprecate_controller_batch(controllers.len() as u32)).into())
2498		}
2499
2500		/// Restores the state of a ledger which is in an inconsistent state.
2501		///
2502		/// The requirements to restore a ledger are the following:
2503		/// * The stash is bonded; or
2504		/// * The stash is not bonded but it has a staking lock left behind; or
2505		/// * If the stash has an associated ledger and its state is inconsistent; or
2506		/// * If the ledger is not corrupted *but* its staking lock is out of sync.
2507		///
2508		/// The `maybe_*` input parameters will overwrite the corresponding data and metadata of the
2509		/// ledger associated with the stash. If the input parameters are not set, the ledger will
2510		/// be reset values from on-chain state.
2511		#[pallet::call_index(29)]
2512		#[pallet::weight(T::WeightInfo::restore_ledger())]
2513		pub fn restore_ledger(
2514			origin: OriginFor<T>,
2515			stash: T::AccountId,
2516			maybe_controller: Option<T::AccountId>,
2517			maybe_total: Option<BalanceOf<T>>,
2518			maybe_unlocking: Option<BoundedVec<UnlockChunk<BalanceOf<T>>, T::MaxUnlockingChunks>>,
2519		) -> DispatchResult {
2520			T::AdminOrigin::ensure_origin(origin)?;
2521
2522			// cannot restore ledger for virtual stakers.
2523			ensure!(!Self::is_virtual_staker(&stash), Error::<T>::VirtualStakerNotAllowed);
2524
2525			let current_lock = asset::staked::<T>(&stash);
2526			let stash_balance = asset::stakeable_balance::<T>(&stash);
2527
2528			let (new_controller, new_total) = match Self::inspect_bond_state(&stash) {
2529				Ok(LedgerIntegrityState::Corrupted) => {
2530					let new_controller = maybe_controller.unwrap_or(stash.clone());
2531
2532					let new_total = if let Some(total) = maybe_total {
2533						let new_total = total.min(stash_balance);
2534						// enforce hold == ledger.amount.
2535						asset::update_stake::<T>(&stash, new_total)?;
2536						new_total
2537					} else {
2538						current_lock
2539					};
2540
2541					Ok((new_controller, new_total))
2542				},
2543				Ok(LedgerIntegrityState::CorruptedKilled) => {
2544					if current_lock == Zero::zero() {
2545						// this case needs to restore both lock and ledger, so the new total needs
2546						// to be given by the called since there's no way to restore the total
2547						// on-chain.
2548						ensure!(maybe_total.is_some(), Error::<T>::CannotRestoreLedger);
2549						Ok((
2550							stash.clone(),
2551							maybe_total.expect("total exists as per the check above; qed."),
2552						))
2553					} else {
2554						Ok((stash.clone(), current_lock))
2555					}
2556				},
2557				Ok(LedgerIntegrityState::LockCorrupted) => {
2558					// ledger is not corrupted but its locks are out of sync. In this case, we need
2559					// to enforce a new ledger.total and staking lock for this stash.
2560					let new_total =
2561						maybe_total.ok_or(Error::<T>::CannotRestoreLedger)?.min(stash_balance);
2562					asset::update_stake::<T>(&stash, new_total)?;
2563
2564					Ok((stash.clone(), new_total))
2565				},
2566				Err(Error::<T>::BadState) => {
2567					// the stash and ledger do not exist but lock is lingering.
2568					asset::kill_stake::<T>(&stash)?;
2569					ensure!(
2570						Self::inspect_bond_state(&stash) == Err(Error::<T>::NotStash),
2571						Error::<T>::BadState
2572					);
2573
2574					return Ok(());
2575				},
2576				Ok(LedgerIntegrityState::Ok) | Err(_) => Err(Error::<T>::CannotRestoreLedger),
2577			}?;
2578
2579			// re-bond stash and controller tuple.
2580			Bonded::<T>::insert(&stash, &new_controller);
2581
2582			// resoter ledger state.
2583			let mut ledger = StakingLedger::<T>::new(stash.clone(), new_total);
2584			ledger.controller = Some(new_controller);
2585			ledger.unlocking = maybe_unlocking.unwrap_or_default();
2586			ledger.update()?;
2587
2588			ensure!(
2589				Self::inspect_bond_state(&stash) == Ok(LedgerIntegrityState::Ok),
2590				Error::<T>::BadState
2591			);
2592			Ok(())
2593		}
2594
2595		/// Migrates permissionlessly a stash from locks to holds.
2596		///
2597		/// This removes the old lock on the stake and creates a hold on it atomically. If all
2598		/// stake cannot be held, the best effort is made to hold as much as possible. The remaining
2599		/// stake is removed from the ledger.
2600		///
2601		/// The fee is waived if the migration is successful.
2602		#[pallet::call_index(30)]
2603		#[pallet::weight(T::WeightInfo::migrate_currency())]
2604		pub fn migrate_currency(
2605			origin: OriginFor<T>,
2606			stash: T::AccountId,
2607		) -> DispatchResultWithPostInfo {
2608			let _ = ensure_signed(origin)?;
2609			Self::do_migrate_currency(&stash)?;
2610
2611			// Refund the transaction fee if successful.
2612			Ok(Pays::No.into())
2613		}
2614
2615		/// Manually and permissionlessly applies a deferred slash for a given era.
2616		///
2617		/// Normally, slashes are automatically applied shortly after the start of the `slash_era`.
2618		/// The automatic application of slashes is handled by the pallet's internal logic, and it
2619		/// tries to apply one slash page per block of the era.
2620		/// If for some reason, one era is not enough for applying all slash pages, the remaining
2621		/// slashes need to be manually (permissionlessly) applied.
2622		///
2623		/// For a given era x, if at era x+1, slashes are still unapplied, all withdrawals get
2624		/// blocked, and these need to be manually applied by calling this function.
2625		/// This function exists as a **fallback mechanism** for this extreme situation, but we
2626		/// never expect to encounter this in normal scenarios.
2627		///
2628		/// The parameters for this call can be queried by looking at the `UnappliedSlashes` storage
2629		/// for eras older than the active era.
2630		///
2631		/// ## Parameters
2632		/// - `slash_era`: The staking era in which the slash was originally scheduled.
2633		/// - `slash_key`: A unique identifier for the slash, represented as a tuple:
2634		///   - `stash`: The stash account of the validator being slashed.
2635		///   - `slash_fraction`: The fraction of the stake that was slashed.
2636		///   - `page_index`: The index of the exposure page being processed.
2637		///
2638		/// ## Behavior
2639		/// - The function is **permissionless**—anyone can call it.
2640		/// - The `slash_era` **must be the current era or a past era**.
2641		/// If it is in the future, the
2642		///   call fails with `EraNotStarted`.
2643		/// - The fee is waived if the slash is successfully applied.
2644		///
2645		/// ## Future Improvement
2646		/// - Implement an **off-chain worker (OCW) task** to automatically apply slashes when there
2647		///   is unused block space, improving efficiency.
2648		#[pallet::call_index(31)]
2649		#[pallet::weight(T::WeightInfo::apply_slash())]
2650		pub fn apply_slash(
2651			origin: OriginFor<T>,
2652			slash_era: EraIndex,
2653			slash_key: (T::AccountId, Perbill, u32),
2654		) -> DispatchResultWithPostInfo {
2655			let _ = ensure_signed(origin)?;
2656			let active_era = ActiveEra::<T>::get().map(|a| a.index).unwrap_or_default();
2657			ensure!(slash_era <= active_era, Error::<T>::EraNotStarted);
2658
2659			// Check if this slash has been cancelled
2660			ensure!(
2661				!Self::check_slash_cancelled(slash_era, &slash_key.0, slash_key.1),
2662				Error::<T>::CancelledSlash
2663			);
2664
2665			let unapplied_slash = UnappliedSlashes::<T>::take(&slash_era, &slash_key)
2666				.ok_or(Error::<T>::InvalidSlashRecord)?;
2667			slashing::apply_slash::<T>(unapplied_slash, slash_era);
2668
2669			Ok(Pays::No.into())
2670		}
2671
2672		/// Perform one step of era pruning to prevent PoV size exhaustion from unbounded deletions.
2673		///
2674		/// This extrinsic enables permissionless lazy pruning of era data by performing
2675		/// incremental deletion of storage items. Each call processes a limited number
2676		/// of items based on available block weight to avoid exceeding block limits.
2677		///
2678		/// Returns `Pays::No` when work is performed to incentivize regular maintenance.
2679		/// Anyone can call this to help maintain the chain's storage health.
2680		///
2681		/// The era must be eligible for pruning (older than HistoryDepth + 1).
2682		/// Check `EraPruningState` storage to see if an era needs pruning before calling.
2683		#[pallet::call_index(32)]
2684		// NOTE: as pre-dispatch weight, use the maximum of all possible pruning step weights
2685		#[pallet::weight({
2686			let v = T::MaxValidatorSet::get();
2687			T::WeightInfo::prune_era_stakers_paged(v)
2688				.max(T::WeightInfo::prune_era_stakers_overview(v))
2689				.max(T::WeightInfo::prune_era_validator_prefs(v))
2690				.max(T::WeightInfo::prune_era_claimed_rewards(v))
2691				.max(T::WeightInfo::prune_era_validator_reward())
2692				.max(T::WeightInfo::prune_era_reward_points())
2693				.max(T::WeightInfo::prune_era_total_stake())
2694		})]
2695		pub fn prune_era_step(origin: OriginFor<T>, era: EraIndex) -> DispatchResultWithPostInfo {
2696			let _ = ensure_signed(origin)?;
2697
2698			// Verify era is eligible for pruning: era <= active_era - history_depth - 1
2699			let active_era = crate::session_rotation::Rotator::<T>::active_era();
2700			let history_depth = T::HistoryDepth::get();
2701			let earliest_prunable_era = active_era.saturating_sub(history_depth).saturating_sub(1);
2702			ensure!(era <= earliest_prunable_era, Error::<T>::EraNotPrunable);
2703
2704			let actual_weight = Self::do_prune_era_step(era)?;
2705
2706			Ok(frame_support::dispatch::PostDispatchInfo {
2707				actual_weight: Some(actual_weight),
2708				pays_fee: frame_support::dispatch::Pays::No,
2709			})
2710		}
2711	}
2712}