From 8af61d03b62d541370015608b48c7399d5f67320 Mon Sep 17 00:00:00 2001
From: Ankan <10196091+Ank4n@users.noreply.github.com>
Date: Fri, 24 Nov 2023 16:31:20 +0100
Subject: [PATCH] [NPoS] Use EraInfo to manipulate exposure in fast-unstake
 tests (#2459)

The FastUnstake pallet tests were previously directly modifying storage
items in the pallet-staking to alter exposure. However, due to the
introduction of the [new paged exposure
feature](https://github.com/paritytech/polkadot-sdk/pull/1189) these
tests were not testing against correct storage items. This issue
resulted in a bug that I didn't catch, which has been addressed in [this
fix](https://github.com/paritytech/polkadot-sdk/pull/2369).

This PR introduces a modification to how the pallet-fast-unstake handles
exposure. It now utilizes `pallet-staking::EraInfo` to set or mutate
Exposures.
---
 substrate/frame/fast-unstake/src/mock.rs  | 11 ++++++-----
 substrate/frame/fast-unstake/src/tests.rs |  8 +++++---
 substrate/frame/staking/src/lib.rs        | 10 +++++-----
 3 files changed, 16 insertions(+), 13 deletions(-)

diff --git a/substrate/frame/fast-unstake/src/mock.rs b/substrate/frame/fast-unstake/src/mock.rs
index df133bdfd47..09a08f222b6 100644
--- a/substrate/frame/fast-unstake/src/mock.rs
+++ b/substrate/frame/fast-unstake/src/mock.rs
@@ -244,7 +244,7 @@ impl ExtBuilder {
 				(v, Exposure { total: 0, own: 0, others })
 			})
 			.for_each(|(validator, exposure)| {
-				pallet_staking::ErasStakers::<T>::insert(era, validator, exposure);
+				pallet_staking::EraInfo::<T>::set_exposure(era, &validator, exposure);
 			});
 	}
 
@@ -342,10 +342,11 @@ pub fn assert_unstaked(stash: &AccountId) {
 }
 
 pub fn create_exposed_nominator(exposed: AccountId, era: u32) {
-	// create an exposed nominator in era 1
-	pallet_staking::ErasStakers::<T>::mutate(era, VALIDATORS_PER_ERA, |expo| {
-		expo.others.push(IndividualExposure { who: exposed, value: 0 as Balance });
-	});
+	// create an exposed nominator in passed era
+	let mut exposure = pallet_staking::EraInfo::<T>::get_full_exposure(era, &VALIDATORS_PER_ERA);
+	exposure.others.push(IndividualExposure { who: exposed, value: 0 as Balance });
+	pallet_staking::EraInfo::<T>::set_exposure(era, &VALIDATORS_PER_ERA, exposure);
+
 	Balances::make_free_balance_be(&exposed, 100);
 	assert_ok!(Staking::bond(
 		RuntimeOrigin::signed(exposed),
diff --git a/substrate/frame/fast-unstake/src/tests.rs b/substrate/frame/fast-unstake/src/tests.rs
index 94ad6a84b85..b19fe3b8c46 100644
--- a/substrate/frame/fast-unstake/src/tests.rs
+++ b/substrate/frame/fast-unstake/src/tests.rs
@@ -788,10 +788,12 @@ mod on_idle {
 			assert_ok!(FastUnstake::register_fast_unstake(RuntimeOrigin::signed(VALIDATOR_PREFIX)));
 
 			// but they indeed are exposed!
-			assert!(pallet_staking::ErasStakers::<T>::contains_key(
+			assert!(pallet_staking::EraInfo::<T>::get_paged_exposure(
 				BondingDuration::get() - 1,
-				VALIDATOR_PREFIX
-			));
+				&VALIDATOR_PREFIX,
+				0
+			)
+			.is_some());
 
 			// process a block, this validator is exposed and has been slashed.
 			next_block(true);
diff --git a/substrate/frame/staking/src/lib.rs b/substrate/frame/staking/src/lib.rs
index e6250bb9681..41cb2a12c3a 100644
--- a/substrate/frame/staking/src/lib.rs
+++ b/substrate/frame/staking/src/lib.rs
@@ -724,7 +724,7 @@ pub struct Nominations<T: Config> {
 /// This is useful where we need to take into account the validator's own stake and total exposure
 /// in consideration, in addition to the individual nominators backing them.
 #[derive(Encode, Decode, RuntimeDebug, TypeInfo, PartialEq, Eq)]
-struct PagedExposure<AccountId, Balance: HasCompact + codec::MaxEncodedLen> {
+pub struct PagedExposure<AccountId, Balance: HasCompact + codec::MaxEncodedLen> {
 	exposure_metadata: PagedExposureMetadata<Balance>,
 	exposure_page: ExposurePage<AccountId, Balance>,
 }
@@ -1017,7 +1017,7 @@ where
 /// Wrapper struct for Era related information. It is not a pure encapsulation as these storage
 /// items can be accessed directly but nevertheless, its recommended to use `EraInfo` where we
 /// can and add more functions to it as needed.
-pub(crate) struct EraInfo<T>(sp_std::marker::PhantomData<T>);
+pub struct EraInfo<T>(sp_std::marker::PhantomData<T>);
 impl<T: Config> EraInfo<T> {
 	/// Temporary function which looks at both (1) passed param `T::StakingLedger` for legacy
 	/// non-paged rewards, and (2) `T::ClaimedRewards` for paged rewards. This function can be
@@ -1047,7 +1047,7 @@ impl<T: Config> EraInfo<T> {
 	///
 	/// This builds a paged exposure from `PagedExposureMetadata` and `ExposurePage` of the
 	/// validator. For older non-paged exposure, it returns the clipped exposure directly.
-	pub(crate) fn get_paged_exposure(
+	pub fn get_paged_exposure(
 		era: EraIndex,
 		validator: &T::AccountId,
 		page: Page,
@@ -1082,7 +1082,7 @@ impl<T: Config> EraInfo<T> {
 	}
 
 	/// Get full exposure of the validator at a given era.
-	pub(crate) fn get_full_exposure(
+	pub fn get_full_exposure(
 		era: EraIndex,
 		validator: &T::AccountId,
 	) -> Exposure<T::AccountId, BalanceOf<T>> {
@@ -1176,7 +1176,7 @@ impl<T: Config> EraInfo<T> {
 	}
 
 	/// Store exposure for elected validators at start of an era.
-	pub(crate) fn set_exposure(
+	pub fn set_exposure(
 		era: EraIndex,
 		validator: &T::AccountId,
 		exposure: Exposure<T::AccountId, BalanceOf<T>>,
-- 
GitLab