Skip to main content

pallet_staking/pallet/
impls.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//! Implementations for the Staking FRAME Pallet.
19
20use frame_election_provider_support::{
21	bounds::{CountBound, SizeBound},
22	data_provider, BoundedSupportsOf, DataProviderBounds, ElectionDataProvider, ElectionProvider,
23	PageIndex, ScoreProvider, SortedListProvider, TryFromOtherBounds, VoteWeight, VoterOf,
24};
25use frame_support::{
26	defensive,
27	dispatch::WithPostDispatchInfo,
28	pallet_prelude::*,
29	traits::{
30		Defensive, DefensiveSaturating, EstimateNextNewSession, Get, Imbalance,
31		InspectLockableCurrency, Len, LockableCurrency, OnUnbalanced, RewardsReporter, TryCollect,
32		UnixTime,
33	},
34	weights::Weight,
35};
36use frame_system::{pallet_prelude::BlockNumberFor, RawOrigin};
37use pallet_session::historical;
38use sp_runtime::{
39	traits::{
40		Bounded, CheckedAdd, Convert, One, SaturatedConversion, Saturating, StaticLookup, Zero,
41	},
42	ArithmeticError, DispatchResult, Perbill, Percent,
43};
44use sp_staking::{
45	currency_to_vote::CurrencyToVote,
46	offence::{OffenceDetails, OnOffenceHandler},
47	EraIndex, OnStakingUpdate, Page, SessionIndex, Stake,
48	StakingAccount::{self, Controller, Stash},
49	StakingInterface,
50};
51
52use crate::{
53	asset, election_size_tracker::StaticTracker, log, slashing, weights::WeightInfo, ActiveEraInfo,
54	BalanceOf, EraInfo, EraPayout, Exposure, Forcing, IndividualExposure, LedgerIntegrityState,
55	MaxNominationsOf, MaxWinnersOf, Nominations, NominationsQuota, PositiveImbalanceOf,
56	RewardDestination, SessionInterface, StakingLedger, UnlockChunk, ValidatorPrefs, STAKING_ID,
57};
58use alloc::{boxed::Box, vec, vec::Vec};
59
60use super::pallet::*;
61
62#[cfg(feature = "try-runtime")]
63use frame_support::ensure;
64#[cfg(any(test, feature = "try-runtime"))]
65use sp_runtime::TryRuntimeError;
66
67/// The maximum number of iterations that we do whilst iterating over `T::VoterList` in
68/// `get_npos_voters`.
69///
70/// In most cases, if we want n items, we iterate exactly n times. In rare cases, if a voter is
71/// invalid (for any reason) the iteration continues. With this constant, we iterate at most 2 * n
72/// times and then give up.
73const NPOS_MAX_ITERATIONS_COEFFICIENT: u32 = 2;
74
75impl<T: Config> Pallet<T> {
76	/// Fetches the ledger associated with a controller or stash account, if any.
77	pub fn ledger(account: StakingAccount<T::AccountId>) -> Result<StakingLedger<T>, Error<T>> {
78		StakingLedger::<T>::get(account)
79	}
80
81	pub fn payee(account: StakingAccount<T::AccountId>) -> Option<RewardDestination<T::AccountId>> {
82		StakingLedger::<T>::reward_destination(account)
83	}
84
85	/// Fetches the controller bonded to a stash account, if any.
86	pub fn bonded(stash: &T::AccountId) -> Option<T::AccountId> {
87		StakingLedger::<T>::paired_account(Stash(stash.clone()))
88	}
89
90	/// Inspects and returns the corruption state of a ledger and direct bond, if any.
91	///
92	/// Note: all operations in this method access the `Bonded` and `Ledger` storage maps directly
93	/// instead of using the [`StakingLedger`] API since the bond and/or ledger may be corrupted.
94	/// The method is also meant to check state for direct bonds and may not work as expected for
95	/// virtual bonds.
96	pub(crate) fn inspect_bond_state(
97		stash: &T::AccountId,
98	) -> Result<LedgerIntegrityState, Error<T>> {
99		let hold_or_lock = match asset::staked::<T>(&stash) {
100			x if x.is_zero() => {
101				let locked = T::OldCurrency::balance_locked(STAKING_ID, &stash).into();
102				locked
103			},
104			held => held,
105		};
106
107		let controller = <Bonded<T>>::get(stash).ok_or_else(|| {
108			if hold_or_lock == Zero::zero() {
109				Error::<T>::NotStash
110			} else {
111				Error::<T>::BadState
112			}
113		})?;
114
115		match Ledger::<T>::get(controller) {
116			Some(ledger) => {
117				if ledger.stash != *stash {
118					Ok(LedgerIntegrityState::Corrupted)
119				} else {
120					if hold_or_lock != ledger.total {
121						Ok(LedgerIntegrityState::LockCorrupted)
122					} else {
123						Ok(LedgerIntegrityState::Ok)
124					}
125				}
126			},
127			None => Ok(LedgerIntegrityState::CorruptedKilled),
128		}
129	}
130
131	/// The total balance that can be slashed from a stash account as of right now.
132	pub fn slashable_balance_of(stash: &T::AccountId) -> BalanceOf<T> {
133		// Weight note: consider making the stake accessible through stash.
134		Self::ledger(Stash(stash.clone())).map(|l| l.active).unwrap_or_default()
135	}
136
137	/// Internal impl of [`Self::slashable_balance_of`] that returns [`VoteWeight`].
138	pub fn slashable_balance_of_vote_weight(
139		stash: &T::AccountId,
140		issuance: BalanceOf<T>,
141	) -> VoteWeight {
142		T::CurrencyToVote::to_vote(Self::slashable_balance_of(stash), issuance)
143	}
144
145	/// Returns a closure around `slashable_balance_of_vote_weight` that can be passed around.
146	///
147	/// This prevents call sites from repeatedly requesting `total_issuance` from backend. But it is
148	/// important to be only used while the total issuance is not changing.
149	pub fn weight_of_fn() -> Box<dyn Fn(&T::AccountId) -> VoteWeight> {
150		// NOTE: changing this to unboxed `impl Fn(..)` return type and the pallet will still
151		// compile, while some types in mock fail to resolve.
152		let issuance = asset::total_issuance::<T>();
153		Box::new(move |who: &T::AccountId| -> VoteWeight {
154			Self::slashable_balance_of_vote_weight(who, issuance)
155		})
156	}
157
158	/// Same as `weight_of_fn`, but made for one time use.
159	pub fn weight_of(who: &T::AccountId) -> VoteWeight {
160		let issuance = asset::total_issuance::<T>();
161		Self::slashable_balance_of_vote_weight(who, issuance)
162	}
163
164	pub(super) fn do_bond_extra(stash: &T::AccountId, additional: BalanceOf<T>) -> DispatchResult {
165		let mut ledger = Self::ledger(StakingAccount::Stash(stash.clone()))?;
166
167		// for virtual stakers, we don't need to check the balance. Since they are only accessed
168		// via low level apis, we can assume that the caller has done the due diligence.
169		let extra = if Self::is_virtual_staker(stash) {
170			additional
171		} else {
172			// additional amount or actual balance of stash whichever is lower.
173			additional.min(asset::free_to_stake::<T>(stash))
174		};
175
176		ledger.total = ledger.total.checked_add(&extra).ok_or(ArithmeticError::Overflow)?;
177		ledger.active = ledger.active.checked_add(&extra).ok_or(ArithmeticError::Overflow)?;
178		// last check: the new active amount of ledger must be more than ED.
179		ensure!(ledger.active >= asset::existential_deposit::<T>(), Error::<T>::InsufficientBond);
180
181		// NOTE: ledger must be updated prior to calling `Self::weight_of`.
182		ledger.update()?;
183		// update this staker in the sorted list, if they exist in it.
184		if T::VoterList::contains(stash) {
185			let _ = T::VoterList::on_update(&stash, Self::weight_of(stash)).defensive();
186		}
187
188		Self::deposit_event(Event::<T>::Bonded { stash: stash.clone(), amount: extra });
189
190		Ok(())
191	}
192
193	pub(super) fn do_withdraw_unbonded(
194		controller: &T::AccountId,
195		num_slashing_spans: u32,
196	) -> Result<Weight, DispatchError> {
197		let mut ledger = Self::ledger(Controller(controller.clone()))?;
198		let (stash, old_total) = (ledger.stash.clone(), ledger.total);
199		if let Some(current_era) = CurrentEra::<T>::get() {
200			ledger = ledger.consolidate_unlocked(current_era)
201		}
202		let new_total = ledger.total;
203
204		let ed = asset::existential_deposit::<T>();
205		let used_weight =
206			if ledger.unlocking.is_empty() && (ledger.active < ed || ledger.active.is_zero()) {
207				// This account must have called `unbond()` with some value that caused the active
208				// portion to fall below existential deposit + will have no more unlocking chunks
209				// left. We can now safely remove all staking-related information.
210				Self::kill_stash(&ledger.stash, num_slashing_spans)?;
211
212				T::WeightInfo::withdraw_unbonded_kill(num_slashing_spans)
213			} else {
214				// This was the consequence of a partial unbond. just update the ledger and move on.
215				ledger.update()?;
216
217				// This is only an update, so we use less overall weight.
218				T::WeightInfo::withdraw_unbonded_update(num_slashing_spans)
219			};
220
221		// `old_total` should never be less than the new total because
222		// `consolidate_unlocked` strictly subtracts balance.
223		if new_total < old_total {
224			// Already checked that this won't overflow by entry condition.
225			let value = old_total.defensive_saturating_sub(new_total);
226			Self::deposit_event(Event::<T>::Withdrawn { stash, amount: value });
227
228			// notify listeners.
229			T::EventListeners::on_withdraw(controller, value);
230		}
231
232		Ok(used_weight)
233	}
234
235	pub(super) fn do_payout_stakers(
236		validator_stash: T::AccountId,
237		era: EraIndex,
238	) -> DispatchResultWithPostInfo {
239		let controller = Self::bonded(&validator_stash).ok_or_else(|| {
240			Error::<T>::NotStash.with_weight(T::WeightInfo::payout_stakers_alive_staked(0))
241		})?;
242
243		let ledger = Self::ledger(StakingAccount::Controller(controller))?;
244		let page = EraInfo::<T>::get_next_claimable_page(era, &validator_stash, &ledger)
245			.ok_or_else(|| {
246				Error::<T>::AlreadyClaimed
247					.with_weight(T::WeightInfo::payout_stakers_alive_staked(0))
248			})?;
249
250		Self::do_payout_stakers_by_page(validator_stash, era, page)
251	}
252
253	pub(super) fn do_payout_stakers_by_page(
254		validator_stash: T::AccountId,
255		era: EraIndex,
256		page: Page,
257	) -> DispatchResultWithPostInfo {
258		// Validate input data
259		let current_era = CurrentEra::<T>::get().ok_or_else(|| {
260			Error::<T>::InvalidEraToReward
261				.with_weight(T::WeightInfo::payout_stakers_alive_staked(0))
262		})?;
263
264		let history_depth = T::HistoryDepth::get();
265		ensure!(
266			era <= current_era && era >= current_era.saturating_sub(history_depth),
267			Error::<T>::InvalidEraToReward
268				.with_weight(T::WeightInfo::payout_stakers_alive_staked(0))
269		);
270
271		ensure!(
272			page < EraInfo::<T>::get_page_count(era, &validator_stash),
273			Error::<T>::InvalidPage.with_weight(T::WeightInfo::payout_stakers_alive_staked(0))
274		);
275
276		// Note: if era has no reward to be claimed, era may be future. It's better to not update
277		// `ledger.legacy_claimed_rewards` in this case.
278		let era_payout = <ErasValidatorReward<T>>::get(&era).ok_or_else(|| {
279			Error::<T>::InvalidEraToReward
280				.with_weight(T::WeightInfo::payout_stakers_alive_staked(0))
281		})?;
282
283		let account = StakingAccount::Stash(validator_stash.clone());
284		let mut ledger = Self::ledger(account.clone()).or_else(|_| {
285			if StakingLedger::<T>::is_bonded(account) {
286				Err(Error::<T>::NotController.into())
287			} else {
288				Err(Error::<T>::NotStash.with_weight(T::WeightInfo::payout_stakers_alive_staked(0)))
289			}
290		})?;
291
292		// clean up older claimed rewards
293		ledger
294			.legacy_claimed_rewards
295			.retain(|&x| x >= current_era.saturating_sub(history_depth));
296		ledger.clone().update()?;
297
298		let stash = ledger.stash.clone();
299
300		if EraInfo::<T>::is_rewards_claimed_with_legacy_fallback(era, &ledger, &stash, page) {
301			return Err(Error::<T>::AlreadyClaimed
302				.with_weight(T::WeightInfo::payout_stakers_alive_staked(0)));
303		} else {
304			EraInfo::<T>::set_rewards_as_claimed(era, &stash, page);
305		}
306
307		let exposure = EraInfo::<T>::get_paged_exposure(era, &stash, page).ok_or_else(|| {
308			Error::<T>::InvalidEraToReward
309				.with_weight(T::WeightInfo::payout_stakers_alive_staked(0))
310		})?;
311
312		// Input data seems good, no errors allowed after this point
313
314		// Get Era reward points. It has TOTAL and INDIVIDUAL
315		// Find the fraction of the era reward that belongs to the validator
316		// Take that fraction of the era's rewards to split to nominator and validator
317		//
318		// Then look at the validator, figure out the proportion of their reward
319		// which goes to them and each of their nominators.
320
321		let era_reward_points = <ErasRewardPoints<T>>::get(&era);
322		let total_reward_points = era_reward_points.total;
323		let validator_reward_points =
324			era_reward_points.individual.get(&stash).copied().unwrap_or_else(Zero::zero);
325
326		// Nothing to do if they have no reward points.
327		if validator_reward_points.is_zero() {
328			return Ok(Some(T::WeightInfo::payout_stakers_alive_staked(0)).into());
329		}
330
331		// This is the fraction of the total reward that the validator and the
332		// nominators will get.
333		let validator_total_reward_part =
334			Perbill::from_rational(validator_reward_points, total_reward_points);
335
336		// This is how much validator + nominators are entitled to.
337		let validator_total_payout = validator_total_reward_part * era_payout;
338
339		let validator_commission = EraInfo::<T>::get_validator_commission(era, &ledger.stash);
340		// total commission validator takes across all nominator pages
341		let validator_total_commission_payout = validator_commission * validator_total_payout;
342
343		let validator_leftover_payout =
344			validator_total_payout.defensive_saturating_sub(validator_total_commission_payout);
345		// Now let's calculate how this is split to the validator.
346		let validator_exposure_part = Perbill::from_rational(exposure.own(), exposure.total());
347		let validator_staking_payout = validator_exposure_part * validator_leftover_payout;
348		let page_stake_part = Perbill::from_rational(exposure.page_total(), exposure.total());
349		// validator commission is paid out in fraction across pages proportional to the page stake.
350		let validator_commission_payout = page_stake_part * validator_total_commission_payout;
351
352		Self::deposit_event(Event::<T>::PayoutStarted {
353			era_index: era,
354			validator_stash: stash.clone(),
355			page,
356			next: EraInfo::<T>::get_next_claimable_page(era, &stash, &ledger),
357		});
358
359		let mut total_imbalance = PositiveImbalanceOf::<T>::zero();
360		// We can now make total validator payout:
361		if let Some((imbalance, dest)) =
362			Self::make_payout(&stash, validator_staking_payout + validator_commission_payout)
363		{
364			Self::deposit_event(Event::<T>::Rewarded { stash, dest, amount: imbalance.peek() });
365			total_imbalance.subsume(imbalance);
366		}
367
368		// Track the number of payout ops to nominators. Note:
369		// `WeightInfo::payout_stakers_alive_staked` always assumes at least a validator is paid
370		// out, so we do not need to count their payout op.
371		let mut nominator_payout_count: u32 = 0;
372
373		// Let's now calculate how this is split to the nominators.
374		// Reward only the clipped exposures. Note this is not necessarily sorted.
375		for nominator in exposure.others().iter() {
376			let nominator_exposure_part = Perbill::from_rational(nominator.value, exposure.total());
377
378			let nominator_reward: BalanceOf<T> =
379				nominator_exposure_part * validator_leftover_payout;
380			// We can now make nominator payout:
381			if let Some((imbalance, dest)) = Self::make_payout(&nominator.who, nominator_reward) {
382				// Note: this logic does not count payouts for `RewardDestination::None`.
383				nominator_payout_count += 1;
384				let e = Event::<T>::Rewarded {
385					stash: nominator.who.clone(),
386					dest,
387					amount: imbalance.peek(),
388				};
389				Self::deposit_event(e);
390				total_imbalance.subsume(imbalance);
391			}
392		}
393
394		T::Reward::on_unbalanced(total_imbalance);
395		debug_assert!(nominator_payout_count <= T::MaxExposurePageSize::get());
396
397		Ok(Some(T::WeightInfo::payout_stakers_alive_staked(nominator_payout_count)).into())
398	}
399
400	/// Chill a stash account.
401	pub(crate) fn chill_stash(stash: &T::AccountId) {
402		let chilled_as_validator = Self::do_remove_validator(stash);
403		let chilled_as_nominator = Self::do_remove_nominator(stash);
404		if chilled_as_validator || chilled_as_nominator {
405			Self::deposit_event(Event::<T>::Chilled { stash: stash.clone() });
406		}
407	}
408
409	/// Actually make a payment to a staker. This uses the currency's reward function
410	/// to pay the right payee for the given staker account.
411	fn make_payout(
412		stash: &T::AccountId,
413		amount: BalanceOf<T>,
414	) -> Option<(PositiveImbalanceOf<T>, RewardDestination<T::AccountId>)> {
415		// noop if amount is zero
416		if amount.is_zero() {
417			return None;
418		}
419		let dest = Self::payee(StakingAccount::Stash(stash.clone()))?;
420
421		let maybe_imbalance = match dest {
422			RewardDestination::Stash => asset::mint_into_existing::<T>(stash, amount),
423			RewardDestination::Staked => Self::ledger(Stash(stash.clone()))
424				.and_then(|mut ledger| {
425					ledger.active += amount;
426					ledger.total += amount;
427					let r = asset::mint_into_existing::<T>(stash, amount);
428
429					let _ = ledger
430						.update()
431						.defensive_proof("ledger fetched from storage, so it exists; qed.");
432
433					Ok(r)
434				})
435				.unwrap_or_default(),
436			RewardDestination::Account(ref dest_account) =>
437				Some(asset::mint_creating::<T>(&dest_account, amount)),
438			RewardDestination::None => None,
439			#[allow(deprecated)]
440			RewardDestination::Controller => Self::bonded(stash)
441					.map(|controller| {
442						defensive!("Paying out controller as reward destination which is deprecated and should be migrated.");
443						// This should never happen once payees with a `Controller` variant have been migrated.
444						// But if it does, just pay the controller account.
445						asset::mint_creating::<T>(&controller, amount)
446		}),
447		};
448		maybe_imbalance.map(|imbalance| (imbalance, dest))
449	}
450
451	/// Plan a new session, potentially triggering a new era.
452	fn new_session(
453		session_index: SessionIndex,
454		is_genesis: bool,
455	) -> Option<BoundedVec<T::AccountId, MaxWinnersOf<T>>> {
456		if let Some(current_era) = CurrentEra::<T>::get() {
457			// Initial era has been set.
458			let current_era_start_session_index = ErasStartSessionIndex::<T>::get(current_era)
459				.unwrap_or_else(|| {
460					frame_support::print("Error: start_session_index must be set for current_era");
461					0
462				});
463
464			let era_length = session_index.saturating_sub(current_era_start_session_index); // Must never happen.
465
466			match ForceEra::<T>::get() {
467				// Will be set to `NotForcing` again if a new era has been triggered.
468				Forcing::ForceNew => (),
469				// Short circuit to `try_trigger_new_era`.
470				Forcing::ForceAlways => (),
471				// Only go to `try_trigger_new_era` if deadline reached.
472				Forcing::NotForcing if era_length >= T::SessionsPerEra::get() => (),
473				_ => {
474					// Either `Forcing::ForceNone`,
475					// or `Forcing::NotForcing if era_length >= T::SessionsPerEra::get()`.
476					return None;
477				},
478			}
479
480			// New era.
481			let maybe_new_era_validators = Self::try_trigger_new_era(session_index, is_genesis);
482			if maybe_new_era_validators.is_some() &&
483				matches!(ForceEra::<T>::get(), Forcing::ForceNew)
484			{
485				Self::set_force_era(Forcing::NotForcing);
486			}
487
488			maybe_new_era_validators
489		} else {
490			// Set initial era.
491			log!(debug, "Starting the first era.");
492			Self::try_trigger_new_era(session_index, is_genesis)
493		}
494	}
495
496	/// Start a session, potentially starting an era.
497	fn start_session(start_session: SessionIndex) {
498		let next_active_era = ActiveEra::<T>::get().map(|e| e.index + 1).unwrap_or(0);
499		// This is only `Some` when current era has already progressed to the next era, while the
500		// active era is one behind (i.e. in the *last session of the active era*, or *first session
501		// of the new current era*, depending on how you look at it).
502		if let Some(next_active_era_start_session_index) =
503			ErasStartSessionIndex::<T>::get(next_active_era)
504		{
505			if next_active_era_start_session_index == start_session {
506				Self::start_era(start_session);
507			} else if next_active_era_start_session_index < start_session {
508				// This arm should never happen, but better handle it than to stall the staking
509				// pallet.
510				frame_support::print("Warning: A session appears to have been skipped.");
511				Self::start_era(start_session);
512			}
513		}
514	}
515
516	/// End a session, potentially ending an era.
517	fn end_session(session_index: SessionIndex) {
518		if let Some(active_era) = ActiveEra::<T>::get() {
519			if let Some(next_active_era_start_session_index) =
520				ErasStartSessionIndex::<T>::get(active_era.index + 1)
521			{
522				if next_active_era_start_session_index == session_index + 1 {
523					Self::end_era(active_era, session_index);
524				}
525			}
526		}
527	}
528
529	/// Start a new era. It does:
530	/// * Increment `active_era.index`,
531	/// * reset `active_era.start`,
532	/// * update `BondedEras` and apply slashes.
533	fn start_era(start_session: SessionIndex) {
534		let active_era = ActiveEra::<T>::mutate(|active_era| {
535			let new_index = active_era.as_ref().map(|info| info.index + 1).unwrap_or(0);
536			*active_era = Some(ActiveEraInfo {
537				index: new_index,
538				// Set new active era start in next `on_finalize`. To guarantee usage of `Time`
539				start: None,
540			});
541			new_index
542		});
543
544		let bonding_duration = T::BondingDuration::get();
545
546		BondedEras::<T>::mutate(|bonded| {
547			bonded.push((active_era, start_session));
548
549			if active_era > bonding_duration {
550				let first_kept = active_era.defensive_saturating_sub(bonding_duration);
551
552				// Prune out everything that's from before the first-kept index.
553				let n_to_prune =
554					bonded.iter().take_while(|&&(era_idx, _)| era_idx < first_kept).count();
555
556				// Kill slashing metadata.
557				for (pruned_era, _) in bonded.drain(..n_to_prune) {
558					slashing::clear_era_metadata::<T>(pruned_era);
559				}
560
561				if let Some(&(_, first_session)) = bonded.first() {
562					T::SessionInterface::prune_historical_up_to(first_session);
563				}
564			}
565		});
566
567		Self::apply_unapplied_slashes(active_era);
568	}
569
570	/// Compute payout for era.
571	fn end_era(active_era: ActiveEraInfo, _session_index: SessionIndex) {
572		// Note: active_era_start can be None if end era is called during genesis config.
573		if let Some(active_era_start) = active_era.start {
574			let now_as_millis_u64 = T::UnixTime::now().as_millis().saturated_into::<u64>();
575
576			let era_duration = (now_as_millis_u64.defensive_saturating_sub(active_era_start))
577				.saturated_into::<u64>();
578			let staked = ErasTotalStake::<T>::get(&active_era.index);
579			let issuance = asset::total_issuance::<T>();
580
581			let (validator_payout, remainder) =
582				T::EraPayout::era_payout(staked, issuance, era_duration);
583
584			let total_payout = validator_payout.saturating_add(remainder);
585			let max_staked_rewards =
586				MaxStakedRewards::<T>::get().unwrap_or(Percent::from_percent(100));
587
588			// apply cap to validators payout and add difference to remainder.
589			let validator_payout = validator_payout.min(max_staked_rewards * total_payout);
590			let remainder = total_payout.saturating_sub(validator_payout);
591
592			Self::deposit_event(Event::<T>::EraPaid {
593				era_index: active_era.index,
594				validator_payout,
595				remainder,
596			});
597
598			// Set ending era reward.
599			<ErasValidatorReward<T>>::insert(&active_era.index, validator_payout);
600			T::RewardRemainder::on_unbalanced(asset::issue::<T>(remainder));
601		}
602	}
603
604	/// Plan a new era.
605	///
606	/// * Bump the current era storage (which holds the latest planned era).
607	/// * Store start session index for the new planned era.
608	/// * Clean old era information.
609	/// * Store staking information for the new planned era
610	///
611	/// Returns the new validator set.
612	pub fn trigger_new_era(
613		start_session_index: SessionIndex,
614		exposures: BoundedVec<
615			(T::AccountId, Exposure<T::AccountId, BalanceOf<T>>),
616			MaxWinnersOf<T>,
617		>,
618	) -> BoundedVec<T::AccountId, MaxWinnersOf<T>> {
619		// Increment or set current era.
620		let new_planned_era = CurrentEra::<T>::mutate(|s| {
621			*s = Some(s.map(|s| s + 1).unwrap_or(0));
622			s.unwrap()
623		});
624		ErasStartSessionIndex::<T>::insert(&new_planned_era, &start_session_index);
625
626		// Clean old era information.
627		if let Some(old_era) = new_planned_era.checked_sub(T::HistoryDepth::get() + 1) {
628			Self::clear_era_information(old_era);
629		}
630
631		// Set staking information for the new era.
632		Self::store_stakers_info(exposures, new_planned_era)
633	}
634
635	/// Potentially plan a new era.
636	///
637	/// Get election result from `T::ElectionProvider`.
638	/// In case election result has more than [`MinimumValidatorCount`] validator trigger a new era.
639	///
640	/// In case a new era is planned, the new validator set is returned.
641	pub(crate) fn try_trigger_new_era(
642		start_session_index: SessionIndex,
643		is_genesis: bool,
644	) -> Option<BoundedVec<T::AccountId, MaxWinnersOf<T>>> {
645		let election_result = if is_genesis {
646			// This pallet only supports single page elections.
647			let result = <T::GenesisElectionProvider>::elect(0)
648				.map_err(|e| {
649					log!(warn, "genesis election provider failed due to {:?}", e);
650					Self::deposit_event(Event::StakingElectionFailed);
651				})
652				.ok()?;
653
654			BoundedSupportsOf::<T::ElectionProvider>::try_from_other_bounds(result).ok()?
655		} else {
656			// This pallet only supports single page elections.
657			<T::ElectionProvider>::elect(0)
658				.map_err(|e| {
659					log!(warn, "election provider failed due to {:?}", e);
660					Self::deposit_event(Event::StakingElectionFailed);
661				})
662				.ok()?
663		};
664
665		let exposures = Self::collect_exposures(election_result);
666		if (exposures.len() as u32) < MinimumValidatorCount::<T>::get().max(1) {
667			// Session will panic if we ever return an empty validator set, thus max(1) ^^.
668			match CurrentEra::<T>::get() {
669				Some(current_era) if current_era > 0 => log!(
670					warn,
671					"chain does not have enough staking candidates to operate for era {:?} ({} \
672					elected, minimum is {})",
673					CurrentEra::<T>::get().unwrap_or(0),
674					exposures.len(),
675					MinimumValidatorCount::<T>::get(),
676				),
677				None => {
678					// The initial era is allowed to have no exposures.
679					// In this case the SessionManager is expected to choose a sensible validator
680					// set.
681					// TODO: this should be simplified #8911
682					CurrentEra::<T>::put(0);
683					ErasStartSessionIndex::<T>::insert(&0, &start_session_index);
684				},
685				_ => (),
686			}
687
688			Self::deposit_event(Event::StakingElectionFailed);
689			return None;
690		}
691
692		Self::deposit_event(Event::StakersElected);
693		Some(Self::trigger_new_era(start_session_index, exposures))
694	}
695
696	/// Process the output of the election.
697	///
698	/// Store staking information for the new planned era
699	pub fn store_stakers_info(
700		exposures: BoundedVec<
701			(T::AccountId, Exposure<T::AccountId, BalanceOf<T>>),
702			MaxWinnersOf<T>,
703		>,
704		new_planned_era: EraIndex,
705	) -> BoundedVec<T::AccountId, MaxWinnersOf<T>> {
706		// Populate elected stash, stakers, exposures, and the snapshot of validator prefs.
707		let mut total_stake: BalanceOf<T> = Zero::zero();
708		let mut elected_stashes = Vec::with_capacity(exposures.len());
709
710		exposures.into_iter().for_each(|(stash, exposure)| {
711			// build elected stash
712			elected_stashes.push(stash.clone());
713			// accumulate total stake
714			total_stake = total_stake.saturating_add(exposure.total);
715			// store staker exposure for this era
716			EraInfo::<T>::set_exposure(new_planned_era, &stash, exposure);
717		});
718
719		let elected_stashes: BoundedVec<_, MaxWinnersOf<T>> = elected_stashes
720			.try_into()
721			.expect("elected_stashes.len() always equal to exposures.len(); qed");
722
723		EraInfo::<T>::set_total_stake(new_planned_era, total_stake);
724
725		// Collect the pref of all winners.
726		for stash in &elected_stashes {
727			let pref = Validators::<T>::get(stash);
728			<ErasValidatorPrefs<T>>::insert(&new_planned_era, stash, pref);
729		}
730
731		if new_planned_era > 0 {
732			log!(
733				debug,
734				"new validator set of size {:?} has been processed for era {:?}",
735				elected_stashes.len(),
736				new_planned_era,
737			);
738		}
739
740		elected_stashes
741	}
742
743	/// Consume a set of [`BoundedSupports`] from [`sp_npos_elections`] and collect them into a
744	/// [`Exposure`].
745	fn collect_exposures(
746		supports: BoundedSupportsOf<T::ElectionProvider>,
747	) -> BoundedVec<(T::AccountId, Exposure<T::AccountId, BalanceOf<T>>), MaxWinnersOf<T>> {
748		let total_issuance = asset::total_issuance::<T>();
749		let to_currency = |e: frame_election_provider_support::ExtendedBalance| {
750			T::CurrencyToVote::to_currency(e, total_issuance)
751		};
752
753		supports
754			.into_iter()
755			.map(|(validator, support)| {
756				// Build `struct exposure` from `support`.
757				let mut others = Vec::with_capacity(support.voters.len());
758				let mut own: BalanceOf<T> = Zero::zero();
759				let mut total: BalanceOf<T> = Zero::zero();
760				support
761					.voters
762					.into_iter()
763					.map(|(nominator, weight)| (nominator, to_currency(weight)))
764					.for_each(|(nominator, stake)| {
765						if nominator == validator {
766							own = own.saturating_add(stake);
767						} else {
768							others.push(IndividualExposure { who: nominator, value: stake });
769						}
770						total = total.saturating_add(stake);
771					});
772
773				let exposure = Exposure { own, others, total };
774				(validator, exposure)
775			})
776			.try_collect()
777			.expect("we only map through support vector which cannot change the size; qed")
778	}
779
780	/// Remove all associated data of a stash account from the staking system.
781	///
782	/// Assumes storage is upgraded before calling.
783	///
784	/// This is called:
785	/// - after a `withdraw_unbonded()` call that frees all of a stash's bonded balance.
786	/// - through `reap_stash()` if the balance has fallen to zero (through slashing).
787	pub(crate) fn kill_stash(stash: &T::AccountId, num_slashing_spans: u32) -> DispatchResult {
788		slashing::clear_stash_metadata::<T>(&stash, num_slashing_spans)?;
789
790		// removes controller from `Bonded` and staking ledger from `Ledger`, as well as reward
791		// setting of the stash in `Payee`.
792		StakingLedger::<T>::kill(&stash)?;
793
794		Self::do_remove_validator(&stash);
795		Self::do_remove_nominator(&stash);
796
797		Ok(())
798	}
799
800	/// Clear all era information for given era.
801	pub(crate) fn clear_era_information(era_index: EraIndex) {
802		// FIXME: We can possibly set a reasonable limit since we do this only once per era and
803		// clean up state across multiple blocks.
804		let mut cursor = <ErasStakers<T>>::clear_prefix(era_index, u32::MAX, None);
805		debug_assert!(cursor.maybe_cursor.is_none());
806		cursor = <ErasStakersClipped<T>>::clear_prefix(era_index, u32::MAX, None);
807		debug_assert!(cursor.maybe_cursor.is_none());
808		cursor = <ErasValidatorPrefs<T>>::clear_prefix(era_index, u32::MAX, None);
809		debug_assert!(cursor.maybe_cursor.is_none());
810		cursor = <ClaimedRewards<T>>::clear_prefix(era_index, u32::MAX, None);
811		debug_assert!(cursor.maybe_cursor.is_none());
812		cursor = <ErasStakersPaged<T>>::clear_prefix((era_index,), u32::MAX, None);
813		debug_assert!(cursor.maybe_cursor.is_none());
814		cursor = <ErasStakersOverview<T>>::clear_prefix(era_index, u32::MAX, None);
815		debug_assert!(cursor.maybe_cursor.is_none());
816
817		<ErasValidatorReward<T>>::remove(era_index);
818		<ErasRewardPoints<T>>::remove(era_index);
819		<ErasTotalStake<T>>::remove(era_index);
820		ErasStartSessionIndex::<T>::remove(era_index);
821	}
822
823	/// Apply previously-unapplied slashes on the beginning of a new era, after a delay.
824	fn apply_unapplied_slashes(active_era: EraIndex) {
825		let era_slashes = UnappliedSlashes::<T>::take(&active_era);
826		log!(
827			debug,
828			"found {} slashes scheduled to be executed in era {:?}",
829			era_slashes.len(),
830			active_era,
831		);
832		for slash in era_slashes {
833			let slash_era = active_era.saturating_sub(T::SlashDeferDuration::get());
834			slashing::apply_slash::<T>(slash, slash_era);
835		}
836	}
837
838	/// Add reward points to validators using their stash account ID.
839	///
840	/// Validators are keyed by stash account ID and must be in the current elected set.
841	///
842	/// For each element in the iterator the given number of points in u32 is added to the
843	/// validator, thus duplicates are handled.
844	///
845	/// At the end of the era each the total payout will be distributed among validator
846	/// relatively to their points.
847	///
848	/// COMPLEXITY: Complexity is `number_of_validator_to_reward x current_elected_len`.
849	fn reward_by_ids(validators_points: impl IntoIterator<Item = (T::AccountId, u32)>) {
850		if let Some(active_era) = ActiveEra::<T>::get() {
851			<ErasRewardPoints<T>>::mutate(active_era.index, |era_rewards| {
852				for (validator, points) in validators_points.into_iter() {
853					*era_rewards.individual.entry(validator).or_default() += points;
854					era_rewards.total += points;
855				}
856			});
857		}
858	}
859
860	/// Helper to set a new `ForceEra` mode.
861	pub(crate) fn set_force_era(mode: Forcing) {
862		log!(info, "Setting force era mode {:?}.", mode);
863		ForceEra::<T>::put(mode);
864		Self::deposit_event(Event::<T>::ForceEra { mode });
865	}
866
867	#[cfg(feature = "runtime-benchmarks")]
868	pub fn add_era_stakers(
869		current_era: EraIndex,
870		stash: T::AccountId,
871		exposure: Exposure<T::AccountId, BalanceOf<T>>,
872	) {
873		EraInfo::<T>::set_exposure(current_era, &stash, exposure);
874	}
875
876	#[cfg(feature = "runtime-benchmarks")]
877	pub fn set_slash_reward_fraction(fraction: Perbill) {
878		SlashRewardFraction::<T>::put(fraction);
879	}
880
881	/// Get all of the voters that are eligible for the npos election.
882	///
883	/// `maybe_max_len` can imposes a cap on the number of voters returned;
884	///
885	/// Sets `MinimumActiveStake` to the minimum active nominator stake in the returned set of
886	/// nominators.
887	///
888	/// This function is self-weighing as [`DispatchClass::Mandatory`].
889	pub fn get_npos_voters(bounds: DataProviderBounds) -> Vec<VoterOf<Self>> {
890		let mut voters_size_tracker: StaticTracker<Self> = StaticTracker::default();
891
892		let final_predicted_len = {
893			let all_voter_count = T::VoterList::count();
894			bounds.count.unwrap_or(all_voter_count.into()).min(all_voter_count.into()).0
895		};
896
897		let mut all_voters = Vec::<_>::with_capacity(final_predicted_len as usize);
898
899		// cache a few things.
900		let weight_of = Self::weight_of_fn();
901
902		let mut voters_seen = 0u32;
903		let mut validators_taken = 0u32;
904		let mut nominators_taken = 0u32;
905		let mut min_active_stake = u64::MAX;
906
907		let mut sorted_voters = T::VoterList::iter();
908		while all_voters.len() < final_predicted_len as usize &&
909			voters_seen < (NPOS_MAX_ITERATIONS_COEFFICIENT * final_predicted_len as u32)
910		{
911			let voter = match sorted_voters.next() {
912				Some(voter) => {
913					voters_seen.saturating_inc();
914					voter
915				},
916				None => break,
917			};
918
919			let voter_weight = weight_of(&voter);
920			// if voter weight is zero, do not consider this voter for the snapshot.
921			if voter_weight.is_zero() {
922				log!(debug, "voter's active balance is 0. skip this voter.");
923				continue;
924			}
925
926			if let Some(Nominations { targets, .. }) = <Nominators<T>>::get(&voter) {
927				if !targets.is_empty() {
928					// Note on lazy nomination quota: we do not check the nomination quota of the
929					// voter at this point and accept all the current nominations. The nomination
930					// quota is only enforced at `nominate` time.
931
932					let voter = (voter, voter_weight, targets);
933					if voters_size_tracker.try_register_voter(&voter, &bounds).is_err() {
934						// no more space left for the election result, stop iterating.
935						Self::deposit_event(Event::<T>::SnapshotVotersSizeExceeded {
936							size: voters_size_tracker.size as u32,
937						});
938						break;
939					}
940
941					all_voters.push(voter);
942					nominators_taken.saturating_inc();
943				} else {
944					// technically should never happen, but not much we can do about it.
945				}
946				min_active_stake =
947					if voter_weight < min_active_stake { voter_weight } else { min_active_stake };
948			} else if Validators::<T>::contains_key(&voter) {
949				// if this voter is a validator:
950				let self_vote = (
951					voter.clone(),
952					voter_weight,
953					vec![voter.clone()]
954						.try_into()
955						.expect("`MaxVotesPerVoter` must be greater than or equal to 1"),
956				);
957
958				if voters_size_tracker.try_register_voter(&self_vote, &bounds).is_err() {
959					// no more space left for the election snapshot, stop iterating.
960					Self::deposit_event(Event::<T>::SnapshotVotersSizeExceeded {
961						size: voters_size_tracker.size as u32,
962					});
963					break;
964				}
965				all_voters.push(self_vote);
966				validators_taken.saturating_inc();
967			} else {
968				// this can only happen if: 1. there a bug in the bags-list (or whatever is the
969				// sorted list) logic and the state of the two pallets is no longer compatible, or
970				// because the nominators is not decodable since they have more nomination than
971				// `T::NominationsQuota::get_quota`. The latter can rarely happen, and is not
972				// really an emergency or bug if it does.
973				defensive!(
974				    "DEFENSIVE: invalid item in `VoterList`: {:?}, this nominator probably has too many nominations now",
975                    voter,
976                );
977			}
978		}
979
980		// all_voters should have not re-allocated.
981		debug_assert!(all_voters.capacity() == final_predicted_len as usize);
982
983		Self::register_weight(T::WeightInfo::get_npos_voters(validators_taken, nominators_taken));
984
985		let min_active_stake: T::CurrencyBalance =
986			if all_voters.is_empty() { Zero::zero() } else { min_active_stake.into() };
987
988		MinimumActiveStake::<T>::put(min_active_stake);
989
990		log!(
991			debug,
992			"generated {} npos voters, {} from validators and {} nominators",
993			all_voters.len(),
994			validators_taken,
995			nominators_taken
996		);
997
998		all_voters
999	}
1000
1001	/// Get the targets for an upcoming npos election.
1002	///
1003	/// This function is self-weighing as [`DispatchClass::Mandatory`].
1004	pub fn get_npos_targets(bounds: DataProviderBounds) -> Vec<T::AccountId> {
1005		let mut targets_size_tracker: StaticTracker<Self> = StaticTracker::default();
1006
1007		let final_predicted_len = {
1008			let all_target_count = T::TargetList::count();
1009			bounds.count.unwrap_or(all_target_count.into()).min(all_target_count.into()).0
1010		};
1011
1012		let mut all_targets = Vec::<T::AccountId>::with_capacity(final_predicted_len as usize);
1013		let mut targets_seen = 0;
1014
1015		let mut targets_iter = T::TargetList::iter();
1016		while all_targets.len() < final_predicted_len as usize &&
1017			targets_seen < (NPOS_MAX_ITERATIONS_COEFFICIENT * final_predicted_len as u32)
1018		{
1019			let target = match targets_iter.next() {
1020				Some(target) => {
1021					targets_seen.saturating_inc();
1022					target
1023				},
1024				None => break,
1025			};
1026
1027			if targets_size_tracker.try_register_target(target.clone(), &bounds).is_err() {
1028				// no more space left for the election snapshot, stop iterating.
1029				Self::deposit_event(Event::<T>::SnapshotTargetsSizeExceeded {
1030					size: targets_size_tracker.size as u32,
1031				});
1032				break;
1033			}
1034
1035			if Validators::<T>::contains_key(&target) {
1036				all_targets.push(target);
1037			}
1038		}
1039
1040		Self::register_weight(T::WeightInfo::get_npos_targets(all_targets.len() as u32));
1041		log!(debug, "generated {} npos targets", all_targets.len());
1042
1043		all_targets
1044	}
1045
1046	/// This function will add a nominator to the `Nominators` storage map,
1047	/// and `VoterList`.
1048	///
1049	/// If the nominator already exists, their nominations will be updated.
1050	///
1051	/// NOTE: you must ALWAYS use this function to add nominator or update their targets. Any access
1052	/// to `Nominators` or `VoterList` outside of this function is almost certainly
1053	/// wrong.
1054	pub fn do_add_nominator(who: &T::AccountId, nominations: Nominations<T>) {
1055		if !Nominators::<T>::contains_key(who) {
1056			// maybe update sorted list.
1057			let _ = T::VoterList::on_insert(who.clone(), Self::weight_of(who))
1058				.defensive_unwrap_or_default();
1059		}
1060		Nominators::<T>::insert(who, nominations);
1061
1062		debug_assert_eq!(
1063			Nominators::<T>::count() + Validators::<T>::count(),
1064			T::VoterList::count()
1065		);
1066	}
1067
1068	/// This function will remove a nominator from the `Nominators` storage map,
1069	/// and `VoterList`.
1070	///
1071	/// Returns true if `who` was removed from `Nominators`, otherwise false.
1072	///
1073	/// NOTE: you must ALWAYS use this function to remove a nominator from the system. Any access to
1074	/// `Nominators` or `VoterList` outside of this function is almost certainly
1075	/// wrong.
1076	pub fn do_remove_nominator(who: &T::AccountId) -> bool {
1077		let outcome = if Nominators::<T>::contains_key(who) {
1078			Nominators::<T>::remove(who);
1079			let _ = T::VoterList::on_remove(who).defensive();
1080			true
1081		} else {
1082			false
1083		};
1084
1085		debug_assert_eq!(
1086			Nominators::<T>::count() + Validators::<T>::count(),
1087			T::VoterList::count()
1088		);
1089
1090		outcome
1091	}
1092
1093	/// This function will add a validator to the `Validators` storage map.
1094	///
1095	/// If the validator already exists, their preferences will be updated.
1096	///
1097	/// NOTE: you must ALWAYS use this function to add a validator to the system. Any access to
1098	/// `Validators` or `VoterList` outside of this function is almost certainly
1099	/// wrong.
1100	pub fn do_add_validator(who: &T::AccountId, prefs: ValidatorPrefs) {
1101		if !Validators::<T>::contains_key(who) {
1102			// maybe update sorted list.
1103			let _ = T::VoterList::on_insert(who.clone(), Self::weight_of(who))
1104				.defensive_unwrap_or_default();
1105		}
1106		Validators::<T>::insert(who, prefs);
1107
1108		debug_assert_eq!(
1109			Nominators::<T>::count() + Validators::<T>::count(),
1110			T::VoterList::count()
1111		);
1112	}
1113
1114	/// This function will remove a validator from the `Validators` storage map.
1115	///
1116	/// Returns true if `who` was removed from `Validators`, otherwise false.
1117	///
1118	/// NOTE: you must ALWAYS use this function to remove a validator from the system. Any access to
1119	/// `Validators` or `VoterList` outside of this function is almost certainly
1120	/// wrong.
1121	pub fn do_remove_validator(who: &T::AccountId) -> bool {
1122		let outcome = if Validators::<T>::contains_key(who) {
1123			Validators::<T>::remove(who);
1124			let _ = T::VoterList::on_remove(who).defensive();
1125			true
1126		} else {
1127			false
1128		};
1129
1130		debug_assert_eq!(
1131			Nominators::<T>::count() + Validators::<T>::count(),
1132			T::VoterList::count()
1133		);
1134
1135		outcome
1136	}
1137
1138	/// Register some amount of weight directly with the system pallet.
1139	///
1140	/// This is always mandatory weight.
1141	fn register_weight(weight: Weight) {
1142		<frame_system::Pallet<T>>::register_extra_weight_unchecked(
1143			weight,
1144			DispatchClass::Mandatory,
1145		);
1146	}
1147
1148	/// Returns full exposure of a validator for a given era.
1149	///
1150	/// History note: This used to be a getter for old storage item `ErasStakers` deprecated in v14.
1151	/// Since this function is used in the codebase at various places, we kept it as a custom getter
1152	/// that takes care of getting the full exposure of the validator in a backward compatible way.
1153	pub fn eras_stakers(
1154		era: EraIndex,
1155		account: &T::AccountId,
1156	) -> Exposure<T::AccountId, BalanceOf<T>> {
1157		EraInfo::<T>::get_full_exposure(era, account)
1158	}
1159
1160	pub(super) fn do_migrate_currency(stash: &T::AccountId) -> DispatchResult {
1161		if Self::is_virtual_staker(stash) {
1162			return Self::do_migrate_virtual_staker(stash);
1163		}
1164
1165		let locked: BalanceOf<T> = T::OldCurrency::balance_locked(STAKING_ID, stash).into();
1166		ensure!(!locked.is_zero(), Error::<T>::AlreadyMigrated);
1167
1168		// remove old staking lock
1169		T::OldCurrency::remove_lock(STAKING_ID, &stash);
1170
1171		// Get rid of the extra consumer we used to have with OldCurrency.
1172		frame_system::Pallet::<T>::dec_consumers(&stash);
1173
1174		let Ok(ledger) = Self::ledger(Stash(stash.clone())) else {
1175			// User is no longer bonded. Removing the lock is enough.
1176			return Ok(());
1177		};
1178
1179		// Ensure we can hold all stake.
1180		let max_hold = asset::stakeable_balance::<T>(&stash);
1181		let force_withdraw = if max_hold >= ledger.total {
1182			// this means we can hold all stake. yay!
1183			asset::update_stake::<T>(&stash, ledger.total)?;
1184			Zero::zero()
1185		} else {
1186			// if we are here, it means we cannot hold all user stake. We will do a force withdraw
1187			// from ledger, but that's okay since anyways user do not have funds for it.
1188			let old_total = ledger.total;
1189			// update ledger with total stake as max_hold.
1190			let updated_ledger = ledger.update_total_stake(max_hold);
1191
1192			// new total stake in ledger.
1193			let new_total = updated_ledger.total;
1194			debug_assert_eq!(new_total, max_hold);
1195
1196			// update ledger in storage.
1197			updated_ledger.update()?;
1198
1199			// return the diff
1200			old_total.defensive_saturating_sub(new_total)
1201		};
1202
1203		Self::deposit_event(Event::<T>::CurrencyMigrated { stash: stash.clone(), force_withdraw });
1204		Ok(())
1205	}
1206
1207	// These are system accounts and don’t normally hold funds, so migration isn’t strictly
1208	// necessary. However, this is a good opportunity to clean up the extra consumer/providers that
1209	// were previously used.
1210	fn do_migrate_virtual_staker(stash: &T::AccountId) -> DispatchResult {
1211		let consumer_count = frame_system::Pallet::<T>::consumers(stash);
1212		// fail early if no consumers.
1213		ensure!(consumer_count > 0, Error::<T>::AlreadyMigrated);
1214
1215		// provider/consumer ref count has been a mess (inconsistent), and some of these accounts
1216		// accumulated upto 2 consumers. But if it's more than 2, we simply fail to not allow
1217		// this migration to be called multiple times.
1218		ensure!(consumer_count <= 2, Error::<T>::BadState);
1219
1220		// get rid of the consumers
1221		for _ in 0..consumer_count {
1222			frame_system::Pallet::<T>::dec_consumers(&stash);
1223		}
1224
1225		// get the current count of providers
1226		let actual_providers = frame_system::Pallet::<T>::providers(stash);
1227
1228		let expected_providers =
1229			// We expect these accounts to have only one provider, and hold no balance. However, if
1230			// someone mischievously sends some funds to these accounts, they may have an additional
1231			// provider, which we can safely ignore.
1232			if asset::free_to_stake::<T>(&stash) >= asset::existential_deposit::<T>() {
1233				2
1234			} else {
1235				1
1236			};
1237
1238		// We should never have more than expected providers.
1239		ensure!(actual_providers <= expected_providers, Error::<T>::BadState);
1240
1241		// if actual provider is less than expected, it is already migrated.
1242		ensure!(actual_providers == expected_providers, Error::<T>::AlreadyMigrated);
1243
1244		frame_system::Pallet::<T>::dec_providers(&stash)?;
1245
1246		Ok(())
1247	}
1248
1249	pub fn on_offence(
1250		offenders: impl Iterator<Item = OffenceDetails<T::AccountId, T::AccountId>>,
1251		slash_fractions: &[Perbill],
1252		slash_session: SessionIndex,
1253	) -> Weight {
1254		let reward_proportion = SlashRewardFraction::<T>::get();
1255		let mut consumed_weight = Weight::from_parts(0, 0);
1256		let mut add_db_reads_writes = |reads, writes| {
1257			consumed_weight += T::DbWeight::get().reads_writes(reads, writes);
1258		};
1259
1260		let active_era = {
1261			let active_era = ActiveEra::<T>::get();
1262			add_db_reads_writes(1, 0);
1263			if active_era.is_none() {
1264				log!(warn, "🦹 on_offence: Active era not set -- not processing offence");
1265				// This offence need not be re-submitted.
1266				return consumed_weight;
1267			}
1268			active_era.expect("value checked not to be `None`; qed").index
1269		};
1270		let active_era_start_session_index = ErasStartSessionIndex::<T>::get(active_era)
1271			.unwrap_or_else(|| {
1272				log!(error, "🦹 on_offence: start_session_index must be set for current_era");
1273				0
1274			});
1275		add_db_reads_writes(1, 0);
1276
1277		let window_start = active_era.saturating_sub(T::BondingDuration::get());
1278
1279		// Fast path for active-era report - most likely.
1280		// `slash_session` cannot be in a future active era. It must be in `active_era` or before.
1281		let slash_era = if slash_session >= active_era_start_session_index {
1282			active_era
1283		} else {
1284			let eras = BondedEras::<T>::get();
1285			add_db_reads_writes(1, 0);
1286
1287			// Reverse because it's more likely to find reports from recent eras.
1288			match eras.iter().rev().find(|&(_, sesh)| sesh <= &slash_session) {
1289				Some((slash_era, _)) => *slash_era,
1290				// Before bonding period. defensive - should be filtered out.
1291				None => {
1292					log!(warn, "🦹 on_offence: bonded era not found");
1293					return consumed_weight;
1294				},
1295			}
1296		};
1297
1298		add_db_reads_writes(1, 1);
1299
1300		let slash_defer_duration = T::SlashDeferDuration::get();
1301
1302		let invulnerables = Invulnerables::<T>::get();
1303		add_db_reads_writes(1, 0);
1304
1305		for (details, slash_fraction) in offenders.zip(slash_fractions) {
1306			let stash = &details.offender;
1307			let exposure = Self::eras_stakers(slash_era, stash);
1308
1309			// Skip if the validator is invulnerable.
1310			if invulnerables.contains(stash) {
1311				continue;
1312			}
1313
1314			Self::deposit_event(Event::<T>::SlashReported {
1315				validator: stash.clone(),
1316				fraction: *slash_fraction,
1317				slash_era,
1318			});
1319
1320			if slash_era == active_era {
1321				// offence is in the current active era. Report it to session to maybe disable the
1322				// validator.
1323				add_db_reads_writes(2, 2);
1324				T::SessionInterface::report_offence(
1325					stash.clone(),
1326					crate::OffenceSeverity(*slash_fraction),
1327				);
1328			}
1329
1330			let unapplied = slashing::compute_slash::<T>(slashing::SlashParams {
1331				stash,
1332				slash: *slash_fraction,
1333				exposure: &exposure,
1334				slash_era,
1335				window_start,
1336				now: active_era,
1337				reward_proportion,
1338			});
1339
1340			if let Some(mut unapplied) = unapplied {
1341				let nominators_len = unapplied.others.len() as u64;
1342				let reporters_len = details.reporters.len() as u64;
1343
1344				{
1345					let upper_bound = 1 /* Validator/NominatorSlashInEra */ + 2 /* fetch_spans */;
1346					let rw = upper_bound + nominators_len * upper_bound;
1347					add_db_reads_writes(rw, rw);
1348				}
1349				unapplied.reporters = details.reporters.clone();
1350				if slash_defer_duration == 0 {
1351					// Apply right away.
1352					slashing::apply_slash::<T>(unapplied, slash_era);
1353					{
1354						let slash_cost = (6, 5);
1355						let reward_cost = (2, 2);
1356						add_db_reads_writes(
1357							(1 + nominators_len) * slash_cost.0 + reward_cost.0 * reporters_len,
1358							(1 + nominators_len) * slash_cost.1 + reward_cost.1 * reporters_len,
1359						);
1360					}
1361				} else {
1362					// Defer to end of some `slash_defer_duration` from now.
1363					log!(
1364						debug,
1365						"deferring slash of {:?} happened in {:?} (reported in {:?}) to {:?}",
1366						slash_fraction,
1367						slash_era,
1368						active_era,
1369						slash_era + slash_defer_duration + 1,
1370					);
1371					UnappliedSlashes::<T>::mutate(
1372						slash_era.saturating_add(slash_defer_duration).saturating_add(One::one()),
1373						move |for_later| for_later.push(unapplied),
1374					);
1375					add_db_reads_writes(1, 1);
1376				}
1377			} else {
1378				add_db_reads_writes(4 /* fetch_spans */, 5 /* kick_out_if_recent */)
1379			}
1380		}
1381
1382		consumed_weight
1383	}
1384
1385	/// Unbonds a controller.
1386	pub(crate) fn do_unbond(
1387		controller: T::AccountId,
1388		value: BalanceOf<T>,
1389	) -> Result<Option<Weight>, DispatchError> {
1390		let unlocking = Self::ledger(Controller(controller.clone())).map(|l| l.unlocking.len())?;
1391
1392		// if there are no unlocking chunks available, try to withdraw chunks older than
1393		// `BondingDuration` to proceed with the unbonding.
1394		let maybe_withdraw_weight = {
1395			if unlocking == T::MaxUnlockingChunks::get() as usize {
1396				let real_num_slashing_spans =
1397					SlashingSpans::<T>::get(&controller).map_or(0, |s| s.iter().count());
1398				Some(Self::do_withdraw_unbonded(&controller, real_num_slashing_spans as u32)?)
1399			} else {
1400				None
1401			}
1402		};
1403
1404		// we need to fetch the ledger again because it may have been mutated in the call
1405		// to `Self::do_withdraw_unbonded` above.
1406		let mut ledger = Self::ledger(Controller(controller))?;
1407		let mut value = value.min(ledger.active);
1408		let stash = ledger.stash.clone();
1409
1410		ensure!(
1411			ledger.unlocking.len() < T::MaxUnlockingChunks::get() as usize,
1412			Error::<T>::NoMoreChunks,
1413		);
1414
1415		if !value.is_zero() {
1416			ledger.active -= value;
1417
1418			// Avoid there being a dust balance left in the staking system.
1419			if ledger.active < asset::existential_deposit::<T>() {
1420				value += ledger.active;
1421				ledger.active = Zero::zero();
1422			}
1423
1424			let min_active_bond = if Nominators::<T>::contains_key(&stash) {
1425				MinNominatorBond::<T>::get()
1426			} else if Validators::<T>::contains_key(&stash) {
1427				MinValidatorBond::<T>::get()
1428			} else {
1429				Zero::zero()
1430			};
1431
1432			// Make sure that the user maintains enough active bond for their role.
1433			// If a user runs into this error, they should chill first.
1434			ensure!(ledger.active >= min_active_bond, Error::<T>::InsufficientBond);
1435
1436			// Note: in case there is no current era it is fine to bond one era more.
1437			let era = CurrentEra::<T>::get()
1438				.unwrap_or(0)
1439				.defensive_saturating_add(T::BondingDuration::get());
1440			if let Some(chunk) = ledger.unlocking.last_mut().filter(|chunk| chunk.era == era) {
1441				// To keep the chunk count down, we only keep one chunk per era. Since
1442				// `unlocking` is a FiFo queue, if a chunk exists for `era` we know that it will
1443				// be the last one.
1444				chunk.value = chunk.value.defensive_saturating_add(value)
1445			} else {
1446				ledger
1447					.unlocking
1448					.try_push(UnlockChunk { value, era })
1449					.map_err(|_| Error::<T>::NoMoreChunks)?;
1450			};
1451			// NOTE: ledger must be updated prior to calling `Self::weight_of`.
1452			ledger.update()?;
1453
1454			// update this staker in the sorted list, if they exist in it.
1455			if T::VoterList::contains(&stash) {
1456				let _ = T::VoterList::on_update(&stash, Self::weight_of(&stash)).defensive();
1457			}
1458
1459			Self::deposit_event(Event::<T>::Unbonded { stash, amount: value });
1460		}
1461
1462		let actual_weight = if let Some(withdraw_weight) = maybe_withdraw_weight {
1463			Some(T::WeightInfo::unbond().saturating_add(withdraw_weight))
1464		} else {
1465			Some(T::WeightInfo::unbond())
1466		};
1467
1468		Ok(actual_weight)
1469	}
1470}
1471
1472impl<T: Config> Pallet<T> {
1473	/// Returns the current nominations quota for nominators.
1474	///
1475	/// Used by the runtime API.
1476	pub fn api_nominations_quota(balance: BalanceOf<T>) -> u32 {
1477		T::NominationsQuota::get_quota(balance)
1478	}
1479
1480	pub fn api_eras_stakers(
1481		era: EraIndex,
1482		account: T::AccountId,
1483	) -> Exposure<T::AccountId, BalanceOf<T>> {
1484		Self::eras_stakers(era, &account)
1485	}
1486
1487	pub fn api_eras_stakers_page_count(era: EraIndex, account: T::AccountId) -> Page {
1488		EraInfo::<T>::get_page_count(era, &account)
1489	}
1490
1491	pub fn api_pending_rewards(era: EraIndex, account: T::AccountId) -> bool {
1492		EraInfo::<T>::pending_rewards(era, &account)
1493	}
1494}
1495
1496impl<T: Config> ElectionDataProvider for Pallet<T> {
1497	type AccountId = T::AccountId;
1498	type BlockNumber = BlockNumberFor<T>;
1499	type MaxVotesPerVoter = MaxNominationsOf<T>;
1500
1501	fn desired_targets() -> data_provider::Result<u32> {
1502		Self::register_weight(T::DbWeight::get().reads(1));
1503		Ok(ValidatorCount::<T>::get())
1504	}
1505
1506	fn electing_voters(
1507		bounds: DataProviderBounds,
1508		_page: PageIndex,
1509	) -> data_provider::Result<Vec<VoterOf<Self>>> {
1510		// This can never fail -- if `maybe_max_len` is `Some(_)` we handle it.
1511		let voters = Self::get_npos_voters(bounds);
1512
1513		debug_assert!(!bounds.exhausted(
1514			SizeBound(voters.encoded_size() as u32).into(),
1515			CountBound(voters.len() as u32).into()
1516		));
1517
1518		Ok(voters)
1519	}
1520
1521	fn electable_targets(
1522		bounds: DataProviderBounds,
1523		_page: PageIndex,
1524	) -> data_provider::Result<Vec<T::AccountId>> {
1525		let targets = Self::get_npos_targets(bounds);
1526
1527		// We can't handle this case yet -- return an error. WIP to improve handling this case in
1528		// <https://github.com/paritytech/substrate/pull/13195>.
1529		if bounds.exhausted(None, CountBound(T::TargetList::count()).into()) {
1530			return Err("Target snapshot too big");
1531		}
1532
1533		debug_assert!(!bounds.exhausted(
1534			SizeBound(targets.encoded_size() as u32).into(),
1535			CountBound(targets.len() as u32).into()
1536		));
1537
1538		Ok(targets)
1539	}
1540
1541	fn next_election_prediction(now: BlockNumberFor<T>) -> BlockNumberFor<T> {
1542		let current_era = CurrentEra::<T>::get().unwrap_or(0);
1543		let current_session = CurrentPlannedSession::<T>::get();
1544		let current_era_start_session_index =
1545			ErasStartSessionIndex::<T>::get(current_era).unwrap_or(0);
1546		// Number of session in the current era or the maximum session per era if reached.
1547		let era_progress = current_session
1548			.saturating_sub(current_era_start_session_index)
1549			.min(T::SessionsPerEra::get());
1550
1551		let until_this_session_end = T::NextNewSession::estimate_next_new_session(now)
1552			.0
1553			.unwrap_or_default()
1554			.saturating_sub(now);
1555
1556		let session_length = T::NextNewSession::average_session_length();
1557
1558		let sessions_left: BlockNumberFor<T> = match ForceEra::<T>::get() {
1559			Forcing::ForceNone => Bounded::max_value(),
1560			Forcing::ForceNew | Forcing::ForceAlways => Zero::zero(),
1561			Forcing::NotForcing if era_progress >= T::SessionsPerEra::get() => Zero::zero(),
1562			Forcing::NotForcing => T::SessionsPerEra::get()
1563				.saturating_sub(era_progress)
1564				// One session is computed in this_session_end.
1565				.saturating_sub(1)
1566				.into(),
1567		};
1568
1569		now.saturating_add(
1570			until_this_session_end.saturating_add(sessions_left.saturating_mul(session_length)),
1571		)
1572	}
1573
1574	#[cfg(feature = "runtime-benchmarks")]
1575	fn add_voter(
1576		voter: T::AccountId,
1577		weight: VoteWeight,
1578		targets: BoundedVec<T::AccountId, Self::MaxVotesPerVoter>,
1579	) {
1580		let stake = <BalanceOf<T>>::try_from(weight).unwrap_or_else(|_| {
1581			panic!("cannot convert a VoteWeight into BalanceOf, benchmark needs reconfiguring.")
1582		});
1583		<Bonded<T>>::insert(voter.clone(), voter.clone());
1584		<Ledger<T>>::insert(voter.clone(), StakingLedger::<T>::new(voter.clone(), stake));
1585
1586		Self::do_add_nominator(&voter, Nominations { targets, submitted_in: 0, suppressed: false });
1587	}
1588
1589	#[cfg(feature = "runtime-benchmarks")]
1590	fn add_target(target: T::AccountId) {
1591		let stake = MinValidatorBond::<T>::get() * 100u32.into();
1592		<Bonded<T>>::insert(target.clone(), target.clone());
1593		<Ledger<T>>::insert(target.clone(), StakingLedger::<T>::new(target.clone(), stake));
1594		Self::do_add_validator(
1595			&target,
1596			ValidatorPrefs { commission: Perbill::zero(), blocked: false },
1597		);
1598	}
1599
1600	#[cfg(feature = "runtime-benchmarks")]
1601	fn clear() {
1602		#[allow(deprecated)]
1603		<Bonded<T>>::remove_all(None);
1604		#[allow(deprecated)]
1605		<Ledger<T>>::remove_all(None);
1606		#[allow(deprecated)]
1607		<Validators<T>>::remove_all();
1608		#[allow(deprecated)]
1609		<Nominators<T>>::remove_all();
1610
1611		T::VoterList::unsafe_clear();
1612	}
1613
1614	#[cfg(feature = "runtime-benchmarks")]
1615	fn put_snapshot(
1616		voters: Vec<VoterOf<Self>>,
1617		targets: Vec<T::AccountId>,
1618		target_stake: Option<VoteWeight>,
1619	) {
1620		targets.into_iter().for_each(|v| {
1621			let stake: BalanceOf<T> = target_stake
1622				.and_then(|w| <BalanceOf<T>>::try_from(w).ok())
1623				.unwrap_or_else(|| MinNominatorBond::<T>::get() * 100u32.into());
1624			<Bonded<T>>::insert(v.clone(), v.clone());
1625			<Ledger<T>>::insert(v.clone(), StakingLedger::<T>::new(v.clone(), stake));
1626			Self::do_add_validator(
1627				&v,
1628				ValidatorPrefs { commission: Perbill::zero(), blocked: false },
1629			);
1630		});
1631
1632		voters.into_iter().for_each(|(v, s, t)| {
1633			let stake = <BalanceOf<T>>::try_from(s).unwrap_or_else(|_| {
1634				panic!("cannot convert a VoteWeight into BalanceOf, benchmark needs reconfiguring.")
1635			});
1636			<Bonded<T>>::insert(v.clone(), v.clone());
1637			<Ledger<T>>::insert(v.clone(), StakingLedger::<T>::new(v.clone(), stake));
1638			Self::do_add_nominator(
1639				&v,
1640				Nominations { targets: t, submitted_in: 0, suppressed: false },
1641			);
1642		});
1643	}
1644}
1645
1646/// In this implementation `new_session(session)` must be called before `end_session(session-1)`
1647/// i.e. the new session must be planned before the ending of the previous session.
1648///
1649/// Once the first new_session is planned, all session must start and then end in order, though
1650/// some session can lag in between the newest session planned and the latest session started.
1651impl<T: Config> pallet_session::SessionManager<T::AccountId> for Pallet<T> {
1652	fn new_session(new_index: SessionIndex) -> Option<Vec<T::AccountId>> {
1653		log!(trace, "planning new session {}", new_index);
1654		CurrentPlannedSession::<T>::put(new_index);
1655		Self::new_session(new_index, false).map(|v| v.into_inner())
1656	}
1657	fn new_session_genesis(new_index: SessionIndex) -> Option<Vec<T::AccountId>> {
1658		log!(trace, "planning new session {} at genesis", new_index);
1659		CurrentPlannedSession::<T>::put(new_index);
1660		Self::new_session(new_index, true).map(|v| v.into_inner())
1661	}
1662	fn start_session(start_index: SessionIndex) {
1663		log!(trace, "starting session {}", start_index);
1664		Self::start_session(start_index)
1665	}
1666	fn end_session(end_index: SessionIndex) {
1667		log!(trace, "ending session {}", end_index);
1668		Self::end_session(end_index)
1669	}
1670}
1671
1672impl<T: Config> historical::SessionManager<T::AccountId, Exposure<T::AccountId, BalanceOf<T>>>
1673	for Pallet<T>
1674{
1675	fn new_session(
1676		new_index: SessionIndex,
1677	) -> Option<Vec<(T::AccountId, Exposure<T::AccountId, BalanceOf<T>>)>> {
1678		<Self as pallet_session::SessionManager<_>>::new_session(new_index).map(|validators| {
1679			validators
1680				.into_iter()
1681				.map(|v| {
1682					let exposure = Exposure::<T::AccountId, BalanceOf<T>>::default();
1683					(v, exposure)
1684				})
1685				.collect()
1686		})
1687	}
1688	fn new_session_genesis(
1689		new_index: SessionIndex,
1690	) -> Option<Vec<(T::AccountId, Exposure<T::AccountId, BalanceOf<T>>)>> {
1691		<Self as pallet_session::SessionManager<_>>::new_session_genesis(new_index).map(
1692			|validators| {
1693				validators
1694					.into_iter()
1695					.map(|v| {
1696						let exposure = Exposure::<T::AccountId, BalanceOf<T>>::default();
1697						(v, exposure)
1698					})
1699					.collect()
1700			},
1701		)
1702	}
1703	fn start_session(start_index: SessionIndex) {
1704		<Self as pallet_session::SessionManager<_>>::start_session(start_index)
1705	}
1706	fn end_session(end_index: SessionIndex) {
1707		<Self as pallet_session::SessionManager<_>>::end_session(end_index)
1708	}
1709}
1710
1711impl<T: Config> historical::SessionManager<T::AccountId, ()> for Pallet<T> {
1712	fn new_session(new_index: SessionIndex) -> Option<Vec<(T::AccountId, ())>> {
1713		<Self as pallet_session::SessionManager<_>>::new_session(new_index)
1714			.map(|validators| validators.into_iter().map(|v| (v, ())).collect())
1715	}
1716	fn new_session_genesis(new_index: SessionIndex) -> Option<Vec<(T::AccountId, ())>> {
1717		<Self as pallet_session::SessionManager<_>>::new_session_genesis(new_index)
1718			.map(|validators| validators.into_iter().map(|v| (v, ())).collect())
1719	}
1720	fn start_session(start_index: SessionIndex) {
1721		<Self as pallet_session::SessionManager<_>>::start_session(start_index)
1722	}
1723	fn end_session(end_index: SessionIndex) {
1724		<Self as pallet_session::SessionManager<_>>::end_session(end_index)
1725	}
1726}
1727
1728/// Add reward points to block authors:
1729/// * 20 points to the block producer for producing a (non-uncle) block,
1730impl<T> pallet_authorship::EventHandler<T::AccountId, BlockNumberFor<T>> for Pallet<T>
1731where
1732	T: Config + pallet_authorship::Config + pallet_session::Config,
1733{
1734	fn note_author(author: T::AccountId) {
1735		<Self as RewardsReporter<T::AccountId>>::reward_by_ids(vec![(author, 20)])
1736	}
1737}
1738
1739/// This is intended to be used with `FilterHistoricalOffences`.
1740impl<T: Config>
1741	OnOffenceHandler<T::AccountId, pallet_session::historical::IdentificationTuple<T>, Weight>
1742	for Pallet<T>
1743where
1744	T: pallet_session::Config<ValidatorId = <T as frame_system::Config>::AccountId>,
1745	T: pallet_session::historical::Config,
1746	T::SessionHandler: pallet_session::SessionHandler<<T as frame_system::Config>::AccountId>,
1747	T::SessionManager: pallet_session::SessionManager<<T as frame_system::Config>::AccountId>,
1748	T::ValidatorIdOf: Convert<
1749		<T as frame_system::Config>::AccountId,
1750		Option<<T as frame_system::Config>::AccountId>,
1751	>,
1752{
1753	fn on_offence(
1754		offenders: &[OffenceDetails<
1755			T::AccountId,
1756			pallet_session::historical::IdentificationTuple<T>,
1757		>],
1758		slash_fractions: &[Perbill],
1759		slash_session: SessionIndex,
1760	) -> Weight {
1761		log!(
1762			debug,
1763			"🦹 on_offence: offenders={:?}, slash_fractions={:?}, slash_session={}",
1764			offenders,
1765			slash_fractions,
1766			slash_session,
1767		);
1768
1769		// the exposure is not actually being used in this implementation
1770		let offenders = offenders.iter().map(|details| {
1771			let (ref offender, _) = details.offender;
1772			OffenceDetails { offender: offender.clone(), reporters: details.reporters.clone() }
1773		});
1774
1775		Self::on_offence(offenders, slash_fractions, slash_session)
1776	}
1777}
1778
1779impl<T: Config> ScoreProvider<T::AccountId> for Pallet<T> {
1780	type Score = VoteWeight;
1781
1782	fn score(who: &T::AccountId) -> Option<Self::Score> {
1783		Self::ledger(Stash(who.clone()))
1784			.map(|l| l.active)
1785			.map(|a| {
1786				let issuance = asset::total_issuance::<T>();
1787				T::CurrencyToVote::to_vote(a, issuance)
1788			})
1789			.ok()
1790	}
1791
1792	#[cfg(feature = "runtime-benchmarks")]
1793	fn set_score_of(who: &T::AccountId, weight: Self::Score) {
1794		// this will clearly results in an inconsistent state, but it should not matter for a
1795		// benchmark.
1796		let active: BalanceOf<T> = weight.try_into().map_err(|_| ()).unwrap();
1797		let mut ledger = match Self::ledger(StakingAccount::Stash(who.clone())) {
1798			Ok(l) => l,
1799			Err(_) => StakingLedger::default_from(who.clone()),
1800		};
1801		ledger.active = active;
1802
1803		<Ledger<T>>::insert(who, ledger);
1804		<Bonded<T>>::insert(who, who);
1805
1806		// also, we play a trick to make sure that a issuance based-`CurrencyToVote` behaves well:
1807		// This will make sure that total issuance is zero, thus the currency to vote will be a 1-1
1808		// conversion.
1809		let imbalance = asset::burn::<T>(asset::total_issuance::<T>());
1810		// kinda ugly, but gets the job done. The fact that this works here is a HUGE exception.
1811		// Don't try this pattern in other places.
1812		core::mem::forget(imbalance);
1813	}
1814}
1815
1816/// A simple sorted list implementation that does not require any additional pallets. Note, this
1817/// does not provide validators in sorted order. If you desire validators in a sorted order take
1818/// a look at `pallet-bags-list`.
1819pub struct UseValidatorsMap<T>(core::marker::PhantomData<T>);
1820impl<T: Config> SortedListProvider<T::AccountId> for UseValidatorsMap<T> {
1821	type Score = BalanceOf<T>;
1822	type Error = ();
1823
1824	/// Returns iterator over voter list, which can have `take` called on it.
1825	fn iter() -> Box<dyn Iterator<Item = T::AccountId>> {
1826		Box::new(Validators::<T>::iter().map(|(v, _)| v))
1827	}
1828	fn iter_from(
1829		start: &T::AccountId,
1830	) -> Result<Box<dyn Iterator<Item = T::AccountId>>, Self::Error> {
1831		if Validators::<T>::contains_key(start) {
1832			let start_key = Validators::<T>::hashed_key_for(start);
1833			Ok(Box::new(Validators::<T>::iter_from(start_key).map(|(n, _)| n)))
1834		} else {
1835			Err(())
1836		}
1837	}
1838	fn count() -> u32 {
1839		Validators::<T>::count()
1840	}
1841	fn contains(id: &T::AccountId) -> bool {
1842		Validators::<T>::contains_key(id)
1843	}
1844	fn on_insert(_: T::AccountId, _weight: Self::Score) -> Result<(), Self::Error> {
1845		// nothing to do on insert.
1846		Ok(())
1847	}
1848	fn get_score(id: &T::AccountId) -> Result<Self::Score, Self::Error> {
1849		Ok(Pallet::<T>::weight_of(id).into())
1850	}
1851	fn on_update(_: &T::AccountId, _weight: Self::Score) -> Result<(), Self::Error> {
1852		// nothing to do on update.
1853		Ok(())
1854	}
1855	fn on_remove(_: &T::AccountId) -> Result<(), Self::Error> {
1856		// nothing to do on remove.
1857		Ok(())
1858	}
1859	fn unsafe_regenerate(
1860		_: impl IntoIterator<Item = T::AccountId>,
1861		_: Box<dyn Fn(&T::AccountId) -> Option<Self::Score>>,
1862	) -> u32 {
1863		// nothing to do upon regenerate.
1864		0
1865	}
1866	#[cfg(feature = "try-runtime")]
1867	fn try_state() -> Result<(), TryRuntimeError> {
1868		Ok(())
1869	}
1870
1871	fn unsafe_clear() {
1872		#[allow(deprecated)]
1873		Validators::<T>::remove_all();
1874	}
1875
1876	#[cfg(feature = "runtime-benchmarks")]
1877	fn score_update_worst_case(_who: &T::AccountId, _is_increase: bool) -> Self::Score {
1878		unimplemented!()
1879	}
1880
1881	fn lock() {}
1882
1883	fn unlock() {}
1884}
1885
1886/// A simple voter list implementation that does not require any additional pallets. Note, this
1887/// does not provide nominators in sorted order. If you desire nominators in a sorted order take
1888/// a look at `pallet-bags-list`.
1889pub struct UseNominatorsAndValidatorsMap<T>(core::marker::PhantomData<T>);
1890impl<T: Config> SortedListProvider<T::AccountId> for UseNominatorsAndValidatorsMap<T> {
1891	type Error = ();
1892	type Score = VoteWeight;
1893
1894	fn iter() -> Box<dyn Iterator<Item = T::AccountId>> {
1895		Box::new(
1896			Validators::<T>::iter()
1897				.map(|(v, _)| v)
1898				.chain(Nominators::<T>::iter().map(|(n, _)| n)),
1899		)
1900	}
1901	fn iter_from(
1902		start: &T::AccountId,
1903	) -> Result<Box<dyn Iterator<Item = T::AccountId>>, Self::Error> {
1904		if Validators::<T>::contains_key(start) {
1905			let start_key = Validators::<T>::hashed_key_for(start);
1906			Ok(Box::new(
1907				Validators::<T>::iter_from(start_key)
1908					.map(|(n, _)| n)
1909					.chain(Nominators::<T>::iter().map(|(x, _)| x)),
1910			))
1911		} else if Nominators::<T>::contains_key(start) {
1912			let start_key = Nominators::<T>::hashed_key_for(start);
1913			Ok(Box::new(Nominators::<T>::iter_from(start_key).map(|(n, _)| n)))
1914		} else {
1915			Err(())
1916		}
1917	}
1918	fn count() -> u32 {
1919		Nominators::<T>::count().saturating_add(Validators::<T>::count())
1920	}
1921	fn contains(id: &T::AccountId) -> bool {
1922		Nominators::<T>::contains_key(id) || Validators::<T>::contains_key(id)
1923	}
1924	fn on_insert(_: T::AccountId, _weight: Self::Score) -> Result<(), Self::Error> {
1925		// nothing to do on insert.
1926		Ok(())
1927	}
1928	fn get_score(id: &T::AccountId) -> Result<Self::Score, Self::Error> {
1929		Ok(Pallet::<T>::weight_of(id))
1930	}
1931	fn on_update(_: &T::AccountId, _weight: Self::Score) -> Result<(), Self::Error> {
1932		// nothing to do on update.
1933		Ok(())
1934	}
1935	fn on_remove(_: &T::AccountId) -> Result<(), Self::Error> {
1936		// nothing to do on remove.
1937		Ok(())
1938	}
1939	fn unsafe_regenerate(
1940		_: impl IntoIterator<Item = T::AccountId>,
1941		_: Box<dyn Fn(&T::AccountId) -> Option<Self::Score>>,
1942	) -> u32 {
1943		// nothing to do upon regenerate.
1944		0
1945	}
1946
1947	#[cfg(feature = "try-runtime")]
1948	fn try_state() -> Result<(), TryRuntimeError> {
1949		Ok(())
1950	}
1951
1952	fn unsafe_clear() {
1953		// NOTE: Caller must ensure this doesn't lead to too many storage accesses. This is a
1954		// condition of SortedListProvider::unsafe_clear.
1955		#[allow(deprecated)]
1956		Nominators::<T>::remove_all();
1957		#[allow(deprecated)]
1958		Validators::<T>::remove_all();
1959	}
1960
1961	#[cfg(feature = "runtime-benchmarks")]
1962	fn score_update_worst_case(_who: &T::AccountId, _is_increase: bool) -> Self::Score {
1963		unimplemented!()
1964	}
1965
1966	fn lock() {}
1967
1968	fn unlock() {}
1969}
1970
1971impl<T: Config> StakingInterface for Pallet<T> {
1972	type AccountId = T::AccountId;
1973	type Balance = BalanceOf<T>;
1974	type CurrencyToVote = T::CurrencyToVote;
1975
1976	fn minimum_nominator_bond() -> Self::Balance {
1977		MinNominatorBond::<T>::get()
1978	}
1979
1980	fn minimum_validator_bond() -> Self::Balance {
1981		MinValidatorBond::<T>::get()
1982	}
1983
1984	fn stash_by_ctrl(controller: &Self::AccountId) -> Result<Self::AccountId, DispatchError> {
1985		Self::ledger(Controller(controller.clone()))
1986			.map(|l| l.stash)
1987			.map_err(|e| e.into())
1988	}
1989
1990	fn bonding_duration() -> EraIndex {
1991		T::BondingDuration::get()
1992	}
1993
1994	fn current_era() -> EraIndex {
1995		CurrentEra::<T>::get().unwrap_or(Zero::zero())
1996	}
1997
1998	fn stake(who: &Self::AccountId) -> Result<Stake<BalanceOf<T>>, DispatchError> {
1999		Self::ledger(Stash(who.clone()))
2000			.map(|l| Stake { total: l.total, active: l.active })
2001			.map_err(|e| e.into())
2002	}
2003
2004	fn bond_extra(who: &Self::AccountId, extra: Self::Balance) -> DispatchResult {
2005		Self::bond_extra(RawOrigin::Signed(who.clone()).into(), extra)
2006	}
2007
2008	fn unbond(who: &Self::AccountId, value: Self::Balance) -> DispatchResult {
2009		let ctrl = Self::bonded(who).ok_or(Error::<T>::NotStash)?;
2010		Self::unbond(RawOrigin::Signed(ctrl).into(), value)
2011			.map_err(|with_post| with_post.error)
2012			.map(|_| ())
2013	}
2014
2015	fn set_payee(stash: &Self::AccountId, reward_acc: &Self::AccountId) -> DispatchResult {
2016		// Since virtual stakers are not allowed to compound their rewards as this pallet does not
2017		// manage their locks, we do not allow reward account to be set same as stash. For
2018		// external pallets that manage the virtual bond, they can claim rewards and re-bond them.
2019		ensure!(
2020			!Self::is_virtual_staker(stash) || stash != reward_acc,
2021			Error::<T>::RewardDestinationRestricted
2022		);
2023
2024		let ledger = Self::ledger(Stash(stash.clone()))?;
2025		ledger
2026			.set_payee(RewardDestination::Account(reward_acc.clone()))
2027			.defensive_proof("ledger was retrieved from storage, thus its bonded; qed.")?;
2028
2029		Ok(())
2030	}
2031
2032	fn chill(who: &Self::AccountId) -> DispatchResult {
2033		// defensive-only: any account bonded via this interface has the stash set as the
2034		// controller, but we have to be sure. Same comment anywhere else that we read this.
2035		let ctrl = Self::bonded(who).ok_or(Error::<T>::NotStash)?;
2036		Self::chill(RawOrigin::Signed(ctrl).into())
2037	}
2038
2039	fn withdraw_unbonded(
2040		who: Self::AccountId,
2041		num_slashing_spans: u32,
2042	) -> Result<bool, DispatchError> {
2043		let ctrl = Self::bonded(&who).ok_or(Error::<T>::NotStash)?;
2044		Self::withdraw_unbonded(RawOrigin::Signed(ctrl.clone()).into(), num_slashing_spans)
2045			.map(|_| !StakingLedger::<T>::is_bonded(StakingAccount::Controller(ctrl)))
2046			.map_err(|with_post| with_post.error)
2047	}
2048
2049	fn bond(
2050		who: &Self::AccountId,
2051		value: Self::Balance,
2052		payee: &Self::AccountId,
2053	) -> DispatchResult {
2054		Self::bond(
2055			RawOrigin::Signed(who.clone()).into(),
2056			value,
2057			RewardDestination::Account(payee.clone()),
2058		)
2059	}
2060
2061	fn nominate(who: &Self::AccountId, targets: Vec<Self::AccountId>) -> DispatchResult {
2062		let ctrl = Self::bonded(who).ok_or(Error::<T>::NotStash)?;
2063		let targets = targets.into_iter().map(T::Lookup::unlookup).collect::<Vec<_>>();
2064		Self::nominate(RawOrigin::Signed(ctrl).into(), targets)
2065	}
2066
2067	fn desired_validator_count() -> u32 {
2068		ValidatorCount::<T>::get()
2069	}
2070
2071	fn election_ongoing() -> bool {
2072		T::ElectionProvider::status().is_ok()
2073	}
2074
2075	fn force_unstake(who: Self::AccountId) -> sp_runtime::DispatchResult {
2076		let num_slashing_spans =
2077			SlashingSpans::<T>::get(&who).map_or(0, |s| s.iter().count() as u32);
2078		Self::force_unstake(RawOrigin::Root.into(), who.clone(), num_slashing_spans)
2079	}
2080
2081	fn is_exposed_in_era(who: &Self::AccountId, era: &EraIndex) -> bool {
2082		// look in the non paged exposures
2083		// FIXME: Can be cleaned up once non paged exposures are cleared (https://github.com/paritytech/polkadot-sdk/issues/433)
2084		ErasStakers::<T>::iter_prefix(era).any(|(validator, exposures)| {
2085			validator == *who || exposures.others.iter().any(|i| i.who == *who)
2086		})
2087			||
2088		// look in the paged exposures
2089		ErasStakersPaged::<T>::iter_prefix((era,)).any(|((validator, _), exposure_page)| {
2090			validator == *who || exposure_page.others.iter().any(|i| i.who == *who)
2091		})
2092	}
2093	fn status(
2094		who: &Self::AccountId,
2095	) -> Result<sp_staking::StakerStatus<Self::AccountId>, DispatchError> {
2096		if !StakingLedger::<T>::is_bonded(StakingAccount::Stash(who.clone())) {
2097			return Err(Error::<T>::NotStash.into());
2098		}
2099
2100		let is_validator = Validators::<T>::contains_key(&who);
2101		let is_nominator = Nominators::<T>::get(&who);
2102
2103		use sp_staking::StakerStatus;
2104		match (is_validator, is_nominator.is_some()) {
2105			(false, false) => Ok(StakerStatus::Idle),
2106			(true, false) => Ok(StakerStatus::Validator),
2107			(false, true) => Ok(StakerStatus::Nominator(
2108				is_nominator.expect("is checked above; qed").targets.into_inner(),
2109			)),
2110			(true, true) => {
2111				defensive!("cannot be both validators and nominator");
2112				Err(Error::<T>::BadState.into())
2113			},
2114		}
2115	}
2116
2117	/// Whether `who` is a virtual staker whose funds are managed by another pallet.
2118	///
2119	/// There is an assumption that, this account is keyless and managed by another pallet in the
2120	/// runtime. Hence, it can never sign its own transactions.
2121	fn is_virtual_staker(who: &T::AccountId) -> bool {
2122		frame_system::Pallet::<T>::account_nonce(who).is_zero() &&
2123			VirtualStakers::<T>::contains_key(who)
2124	}
2125
2126	fn slash_reward_fraction() -> Perbill {
2127		SlashRewardFraction::<T>::get()
2128	}
2129
2130	sp_staking::runtime_benchmarks_enabled! {
2131		fn nominations(who: &Self::AccountId) -> Option<Vec<T::AccountId>> {
2132			Nominators::<T>::get(who).map(|n| n.targets.into_inner())
2133		}
2134
2135		fn add_era_stakers(
2136			current_era: &EraIndex,
2137			stash: &T::AccountId,
2138			exposures: Vec<(Self::AccountId, Self::Balance)>,
2139		) {
2140			let others = exposures
2141				.iter()
2142				.map(|(who, value)| IndividualExposure { who: who.clone(), value: *value })
2143				.collect::<Vec<_>>();
2144			let exposure = Exposure { total: Default::default(), own: Default::default(), others };
2145			EraInfo::<T>::set_exposure(*current_era, stash, exposure);
2146		}
2147
2148		fn max_exposure_page_size() -> Page {
2149			T::MaxExposurePageSize::get()
2150		}
2151	}
2152
2153	sp_staking::std_or_benchmarks_enabled! {
2154		fn set_era(era: EraIndex) {
2155			ActiveEra::<T>::put(ActiveEraInfo { index: era, start: None });
2156			CurrentEra::<T>::put(era);
2157		}
2158	}
2159}
2160
2161impl<T: Config> sp_staking::StakingUnchecked for Pallet<T> {
2162	fn migrate_to_virtual_staker(who: &Self::AccountId) -> DispatchResult {
2163		asset::kill_stake::<T>(who)?;
2164		VirtualStakers::<T>::insert(who, ());
2165		Ok(())
2166	}
2167
2168	/// Virtually bonds `keyless_who` to `payee` with `value`.
2169	///
2170	/// The payee must not be the same as the `keyless_who`.
2171	fn virtual_bond(
2172		keyless_who: &Self::AccountId,
2173		value: Self::Balance,
2174		payee: &Self::AccountId,
2175	) -> DispatchResult {
2176		if StakingLedger::<T>::is_bonded(StakingAccount::Stash(keyless_who.clone())) {
2177			return Err(Error::<T>::AlreadyBonded.into());
2178		}
2179
2180		// check if payee not same as who.
2181		ensure!(keyless_who != payee, Error::<T>::RewardDestinationRestricted);
2182
2183		// mark who as a virtual staker.
2184		VirtualStakers::<T>::insert(keyless_who, ());
2185
2186		Self::deposit_event(Event::<T>::Bonded { stash: keyless_who.clone(), amount: value });
2187		let ledger = StakingLedger::<T>::new(keyless_who.clone(), value);
2188
2189		ledger.bond(RewardDestination::Account(payee.clone()))?;
2190
2191		Ok(())
2192	}
2193
2194	/// Only meant to be used in tests.
2195	#[cfg(feature = "runtime-benchmarks")]
2196	fn migrate_to_direct_staker(who: &Self::AccountId) {
2197		assert!(VirtualStakers::<T>::contains_key(who));
2198		let ledger = StakingLedger::<T>::get(Stash(who.clone())).unwrap();
2199		let _ = asset::update_stake::<T>(who, ledger.total)
2200			.expect("funds must be transferred to stash");
2201		VirtualStakers::<T>::remove(who);
2202	}
2203}
2204
2205impl<T: Config> RewardsReporter<T::AccountId> for Pallet<T> {
2206	fn reward_by_ids(validators_points: impl IntoIterator<Item = (T::AccountId, u32)>) {
2207		Self::reward_by_ids(validators_points)
2208	}
2209}
2210
2211#[cfg(any(test, feature = "try-runtime"))]
2212impl<T: Config> Pallet<T> {
2213	pub(crate) fn do_try_state(_: BlockNumberFor<T>) -> Result<(), TryRuntimeError> {
2214		ensure!(
2215			T::VoterList::iter()
2216				.all(|x| <Nominators<T>>::contains_key(&x) || <Validators<T>>::contains_key(&x)),
2217			"VoterList contains non-staker"
2218		);
2219
2220		use frame_support::traits::fungible::Inspect;
2221		if T::CurrencyToVote::will_downscale(T::Currency::total_issuance()).map_or(false, |x| x) {
2222			log!(warn, "total issuance will cause T::CurrencyToVote to downscale -- report to maintainers.")
2223		}
2224
2225		Self::check_ledgers()?;
2226		Self::check_bonded_consistency()?;
2227		Self::check_payees()?;
2228		Self::check_nominators()?;
2229		Self::check_exposures()?;
2230		Self::check_paged_exposures()?;
2231		Self::check_count()
2232	}
2233
2234	/// Invariants:
2235	/// * A controller should not be associated with more than one ledger.
2236	/// * A bonded (stash, controller) pair should have only one associated ledger. I.e. if the
2237	///   ledger is bonded by stash, the controller account must not bond a different ledger.
2238	/// * A bonded (stash, controller) pair must have an associated ledger.
2239	///
2240	/// NOTE: these checks result in warnings only. Once
2241	/// <https://github.com/paritytech/polkadot-sdk/issues/3245> is resolved, turn warns into check
2242	/// failures.
2243	fn check_bonded_consistency() -> Result<(), TryRuntimeError> {
2244		use alloc::collections::btree_set::BTreeSet;
2245
2246		let mut count_controller_double = 0;
2247		let mut count_double = 0;
2248		let mut count_none = 0;
2249		// sanity check to ensure that each controller in Bonded storage is associated with only one
2250		// ledger.
2251		let mut controllers = BTreeSet::new();
2252
2253		for (stash, controller) in <Bonded<T>>::iter() {
2254			if !controllers.insert(controller.clone()) {
2255				count_controller_double += 1;
2256			}
2257
2258			match (<Ledger<T>>::get(&stash), <Ledger<T>>::get(&controller)) {
2259				(Some(_), Some(_)) =>
2260				// if stash == controller, it means that the ledger has migrated to
2261				// post-controller. If no migration happened, we expect that the (stash,
2262				// controller) pair has only one associated ledger.
2263				{
2264					if stash != controller {
2265						count_double += 1;
2266					}
2267				},
2268				(None, None) => {
2269					count_none += 1;
2270				},
2271				_ => {},
2272			};
2273		}
2274
2275		if count_controller_double != 0 {
2276			log!(
2277				warn,
2278				"a controller is associated with more than one ledger ({} occurrences)",
2279				count_controller_double
2280			);
2281		};
2282
2283		if count_double != 0 {
2284			log!(warn, "single tuple of (stash, controller) pair bonds more than one ledger ({} occurrences)", count_double);
2285		}
2286
2287		if count_none != 0 {
2288			log!(warn, "inconsistent bonded state: (stash, controller) pair missing associated ledger ({} occurrences)", count_none);
2289		}
2290
2291		Ok(())
2292	}
2293
2294	/// Invariants:
2295	/// * A bonded ledger should always have an assigned `Payee`.
2296	/// * The number of entries in `Payee` and of bonded staking ledgers *must* match.
2297	/// * The stash account in the ledger must match that of the bonded account.
2298	fn check_payees() -> Result<(), TryRuntimeError> {
2299		for (stash, _) in Bonded::<T>::iter() {
2300			ensure!(Payee::<T>::get(&stash).is_some(), "bonded ledger does not have payee set");
2301		}
2302
2303		ensure!(
2304			(Ledger::<T>::iter().count() == Payee::<T>::iter().count()) &&
2305				(Ledger::<T>::iter().count() == Bonded::<T>::iter().count()),
2306			"number of entries in payee storage items does not match the number of bonded ledgers",
2307		);
2308
2309		Ok(())
2310	}
2311
2312	/// Invariants:
2313	/// * Number of voters in `VoterList` match that of the number of Nominators and Validators in
2314	/// the system (validator is both voter and target).
2315	/// * Number of targets in `TargetList` matches the number of validators in the system.
2316	/// * Current validator count is bounded by the election provider's max winners.
2317	fn check_count() -> Result<(), TryRuntimeError> {
2318		ensure!(
2319			<T as Config>::VoterList::count() ==
2320				Nominators::<T>::count() + Validators::<T>::count(),
2321			"wrong external count"
2322		);
2323		ensure!(
2324			<T as Config>::TargetList::count() == Validators::<T>::count(),
2325			"wrong external count"
2326		);
2327
2328		let max_validators_bound = MaxWinnersOf::<T>::get();
2329		let max_winners_per_page_bound = crate::MaxWinnersPerPageOf::<T::ElectionProvider>::get();
2330
2331		ensure!(
2332			max_validators_bound >= max_winners_per_page_bound,
2333			"max validators should be higher than per page bounds"
2334		);
2335
2336		ensure!(ValidatorCount::<T>::get() <= max_validators_bound, Error::<T>::TooManyValidators);
2337		Ok(())
2338	}
2339
2340	/// Invariants:
2341	/// * Stake consistency: ledger.total == ledger.active + sum(ledger.unlocking).
2342	/// * The ledger's controller and stash matches the associated `Bonded` tuple.
2343	/// * Staking locked funds for every bonded stash (non virtual stakers) should be the same as
2344	/// its ledger's total.
2345	/// * For virtual stakers, locked funds should be zero and payee should be non-stash account.
2346	/// * Staking ledger and bond are not corrupted.
2347	fn check_ledgers() -> Result<(), TryRuntimeError> {
2348		Bonded::<T>::iter()
2349			.map(|(stash, ctrl)| {
2350				// ensure locks consistency.
2351				if VirtualStakers::<T>::contains_key(stash.clone()) {
2352					ensure!(
2353						asset::staked::<T>(&stash) == Zero::zero(),
2354						"virtual stakers should not have any staked balance"
2355					);
2356					ensure!(
2357						<Bonded<T>>::get(stash.clone()).unwrap() == stash.clone(),
2358						"stash and controller should be same"
2359					);
2360					ensure!(
2361						Ledger::<T>::get(stash.clone()).unwrap().stash == stash,
2362						"ledger corrupted for virtual staker"
2363					);
2364					ensure!(
2365						frame_system::Pallet::<T>::account_nonce(&stash).is_zero(),
2366						"virtual stakers are keyless and should not have any nonce"
2367					);
2368					let reward_destination = <Payee<T>>::get(stash.clone()).unwrap();
2369					if let RewardDestination::Account(payee) = reward_destination {
2370						ensure!(
2371							payee != stash.clone(),
2372							"reward destination should not be same as stash for virtual staker"
2373						);
2374					} else {
2375						return Err(DispatchError::Other(
2376							"reward destination must be of account variant for virtual staker",
2377						));
2378					}
2379				} else {
2380					ensure!(
2381						Self::inspect_bond_state(&stash) == Ok(LedgerIntegrityState::Ok),
2382						"bond, ledger and/or staking hold inconsistent for a bonded stash."
2383					);
2384				}
2385
2386				// ensure ledger consistency.
2387				Self::ensure_ledger_consistent(ctrl)
2388			})
2389			.collect::<Result<Vec<_>, _>>()?;
2390		Ok(())
2391	}
2392
2393	/// Invariants:
2394	/// * For each era exposed validator, check if the exposure total is sane (exposure.total  =
2395	/// exposure.own + exposure.own).
2396	fn check_exposures() -> Result<(), TryRuntimeError> {
2397		let era = ActiveEra::<T>::get().unwrap().index;
2398		ErasStakers::<T>::iter_prefix_values(era)
2399			.map(|expo| {
2400				ensure!(
2401					expo.total ==
2402						expo.own +
2403							expo.others
2404								.iter()
2405								.map(|e| e.value)
2406								.fold(Zero::zero(), |acc, x| acc + x),
2407					"wrong total exposure.",
2408				);
2409				Ok(())
2410			})
2411			.collect::<Result<(), TryRuntimeError>>()
2412	}
2413
2414	/// Invariants:
2415	/// * For each paged era exposed validator, check if the exposure total is sane (exposure.total
2416	/// = exposure.own + exposure.own).
2417	/// * Paged exposures metadata (`ErasStakersOverview`) matches the paged exposures state.
2418	fn check_paged_exposures() -> Result<(), TryRuntimeError> {
2419		use alloc::collections::btree_map::BTreeMap;
2420		use sp_staking::PagedExposureMetadata;
2421
2422		// Sanity check for the paged exposure of the active era.
2423		let mut exposures: BTreeMap<T::AccountId, PagedExposureMetadata<BalanceOf<T>>> =
2424			BTreeMap::new();
2425		let era = ActiveEra::<T>::get().unwrap().index;
2426		let accumulator_default = PagedExposureMetadata {
2427			total: Zero::zero(),
2428			own: Zero::zero(),
2429			nominator_count: 0,
2430			page_count: 0,
2431		};
2432
2433		ErasStakersPaged::<T>::iter_prefix((era,))
2434			.map(|((validator, _page), expo)| {
2435				ensure!(
2436					expo.page_total ==
2437						expo.others.iter().map(|e| e.value).fold(Zero::zero(), |acc, x| acc + x),
2438					"wrong total exposure for the page.",
2439				);
2440
2441				let metadata = exposures.get(&validator).unwrap_or(&accumulator_default);
2442				exposures.insert(
2443					validator,
2444					PagedExposureMetadata {
2445						total: metadata.total + expo.page_total,
2446						own: metadata.own,
2447						nominator_count: metadata.nominator_count + expo.others.len() as u32,
2448						page_count: metadata.page_count + 1,
2449					},
2450				);
2451
2452				Ok(())
2453			})
2454			.collect::<Result<(), TryRuntimeError>>()?;
2455
2456		exposures
2457			.iter()
2458			.map(|(validator, metadata)| {
2459				let actual_overview = ErasStakersOverview::<T>::get(era, validator);
2460
2461				ensure!(actual_overview.is_some(), "No overview found for a paged exposure");
2462				let actual_overview = actual_overview.unwrap();
2463
2464				ensure!(
2465					actual_overview.total == metadata.total + actual_overview.own,
2466					"Exposure metadata does not have correct total exposed stake."
2467				);
2468				ensure!(
2469					actual_overview.nominator_count == metadata.nominator_count,
2470					"Exposure metadata does not have correct count of nominators."
2471				);
2472				ensure!(
2473					actual_overview.page_count == metadata.page_count,
2474					"Exposure metadata does not have correct count of pages."
2475				);
2476
2477				Ok(())
2478			})
2479			.collect::<Result<(), TryRuntimeError>>()
2480	}
2481
2482	/// Invariants:
2483	/// * Checks that each nominator has its entire stake correctly distributed.
2484	fn check_nominators() -> Result<(), TryRuntimeError> {
2485		// a check per nominator to ensure their entire stake is correctly distributed. Will only
2486		// kick-in if the nomination was submitted before the current era.
2487		let era = ActiveEra::<T>::get().unwrap().index;
2488
2489		// cache era exposures to avoid too many db reads.
2490		let era_exposures = T::SessionInterface::validators()
2491			.iter()
2492			.map(|v| Self::eras_stakers(era, v))
2493			.collect::<Vec<_>>();
2494
2495		<Nominators<T>>::iter()
2496			.filter_map(
2497				|(nominator, nomination)| {
2498					if nomination.submitted_in < era {
2499						Some(nominator)
2500					} else {
2501						None
2502					}
2503				},
2504			)
2505			.map(|nominator| -> Result<(), TryRuntimeError> {
2506				// must be bonded.
2507				Self::ensure_is_stash(&nominator)?;
2508				let mut sum_exposed = BalanceOf::<T>::zero();
2509				era_exposures
2510					.iter()
2511					.map(|e| -> Result<(), TryRuntimeError> {
2512						let individual =
2513							e.others.iter().filter(|e| e.who == nominator).collect::<Vec<_>>();
2514						let len = individual.len();
2515						match len {
2516							0 => { /* not supporting this validator at all. */ },
2517							1 => sum_exposed += individual[0].value,
2518							_ => {
2519								return Err(
2520									"nominator cannot back a validator more than once.".into()
2521								)
2522							},
2523						};
2524						Ok(())
2525					})
2526					.collect::<Result<Vec<_>, _>>()?;
2527
2528				// We take total instead of active as the nominator might have requested to unbond
2529				// some of their stake that is still exposed in the current era.
2530				if sum_exposed > Self::ledger(Stash(nominator.clone()))?.total {
2531					// This can happen when there is a slash in the current era so we only warn.
2532					log!(
2533						warn,
2534						"nominator {:?} stake {:?} exceeds the sum_exposed of exposures {:?}.",
2535						nominator,
2536						Self::ledger(Stash(nominator.clone()))?.total,
2537						sum_exposed,
2538					);
2539				}
2540
2541				Ok(())
2542			})
2543			.collect::<Result<Vec<_>, _>>()?;
2544
2545		Ok(())
2546	}
2547
2548	fn ensure_is_stash(who: &T::AccountId) -> Result<(), &'static str> {
2549		ensure!(Self::bonded(who).is_some(), "Not a stash.");
2550		Ok(())
2551	}
2552
2553	fn ensure_ledger_consistent(ctrl: T::AccountId) -> Result<(), TryRuntimeError> {
2554		// ensures ledger.total == ledger.active + sum(ledger.unlocking).
2555		let ledger = Self::ledger(StakingAccount::Controller(ctrl.clone()))?;
2556
2557		let real_total: BalanceOf<T> =
2558			ledger.unlocking.iter().fold(ledger.active, |a, c| a + c.value);
2559		ensure!(real_total == ledger.total, "ledger.total corrupt");
2560
2561		Ok(())
2562	}
2563}