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