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