referrerpolicy=no-referrer-when-downgrade

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