From 9128dca3c544a5327f0a89241aea1409d67c81b0 Mon Sep 17 00:00:00 2001
From: Ankan <10196091+Ank4n@users.noreply.github.com>
Date: Mon, 7 Oct 2024 18:37:34 +0200
Subject: [PATCH] [Staking] Noop refactor to prep pallet for currency fungible
 migration (#5399)

This is a no-op refactor of staking pallet to move all `T::Currency` api
calls under one module.

A followup PR (https://github.com/paritytech/polkadot-sdk/pull/5501)
will implement the Currency <> Fungible migration for the pallet.

Introduces the new `asset` module that centralizes all interaction with
`T::Currency`. This is an attempt to try minimising staking logic
changes to minimal parts of the codebase.

## Things of note
- `T::Currency::free_balance` in current implementation includes both
staked (locked) and liquid tokens (kinda sounds wrong to call it free
then). This PR renames it to `stakeable_balance` (any better name
suggestions?). With #5501, this will become `free balance that can be
held/staked` + `already held/staked balance`.
---
 .../frame/delegated-staking/src/impls.rs      |   4 +-
 .../frame/delegated-staking/src/tests.rs      |   2 +-
 .../test-staking-e2e/src/lib.rs               |  41 +-
 .../test-staking-e2e/src/mock.rs              |   5 +-
 substrate/frame/fast-unstake/src/tests.rs     |  20 +-
 .../benchmarking/src/inner.rs                 |   4 +-
 .../frame/nomination-pools/src/adapter.rs     |   2 +-
 .../frame/offences/benchmarking/src/inner.rs  |  63 +--
 substrate/frame/root-offences/src/tests.rs    |  19 +-
 substrate/frame/staking/src/asset.rs          | 125 +++++
 substrate/frame/staking/src/benchmarking.rs   |  63 +--
 substrate/frame/staking/src/ledger.rs         |  18 +-
 substrate/frame/staking/src/lib.rs            |   1 +
 substrate/frame/staking/src/pallet/impls.rs   |  45 +-
 substrate/frame/staking/src/pallet/mod.rs     |  53 +--
 substrate/frame/staking/src/slashing.rs       |  14 +-
 substrate/frame/staking/src/testing_utils.rs  |  14 +-
 substrate/frame/staking/src/tests.rs          | 435 +++++++++---------
 substrate/primitives/staking/src/lib.rs       |   2 +-
 19 files changed, 538 insertions(+), 392 deletions(-)
 create mode 100644 substrate/frame/staking/src/asset.rs

diff --git a/substrate/frame/delegated-staking/src/impls.rs b/substrate/frame/delegated-staking/src/impls.rs
index 4e6812dee24..a443df7b20f 100644
--- a/substrate/frame/delegated-staking/src/impls.rs
+++ b/substrate/frame/delegated-staking/src/impls.rs
@@ -124,7 +124,7 @@ impl<T: Config> DelegationMigrator for Pallet<T> {
 
 	/// Only used for testing.
 	#[cfg(feature = "runtime-benchmarks")]
-	fn migrate_to_direct_staker(agent: Agent<Self::AccountId>) {
+	fn force_kill_agent(agent: Agent<Self::AccountId>) {
 		<Agents<T>>::remove(agent.clone().get());
 		<Delegators<T>>::iter()
 			.filter(|(_, delegation)| delegation.agent == agent.clone().get())
@@ -136,8 +136,6 @@ impl<T: Config> DelegationMigrator for Pallet<T> {
 				);
 				<Delegators<T>>::remove(&delegator);
 			});
-
-		T::CoreStaking::migrate_to_direct_staker(&agent.get());
 	}
 }
 
diff --git a/substrate/frame/delegated-staking/src/tests.rs b/substrate/frame/delegated-staking/src/tests.rs
index 2c965e18b1b..b7b82a43771 100644
--- a/substrate/frame/delegated-staking/src/tests.rs
+++ b/substrate/frame/delegated-staking/src/tests.rs
@@ -676,7 +676,7 @@ mod staking_integration {
 			// in equal parts. lets try to migrate this nominator into delegate based stake.
 
 			// all balance currently is in 200
-			assert_eq!(Balances::free_balance(agent), agent_amount);
+			assert_eq!(pallet_staking::asset::stakeable_balance::<T>(&agent), agent_amount);
 
 			// to migrate, nominator needs to set an account as a proxy delegator where staked funds
 			// will be moved and delegated back to this old nominator account. This should be funded
diff --git a/substrate/frame/election-provider-multi-phase/test-staking-e2e/src/lib.rs b/substrate/frame/election-provider-multi-phase/test-staking-e2e/src/lib.rs
index 0dc202ff211..13514969438 100644
--- a/substrate/frame/election-provider-multi-phase/test-staking-e2e/src/lib.rs
+++ b/substrate/frame/election-provider-multi-phase/test-staking-e2e/src/lib.rs
@@ -322,24 +322,24 @@ fn automatic_unbonding_pools() {
 		assert_eq!(<Runtime as pallet_nomination_pools::Config>::MaxUnbonding::get(), 1);
 
 		// init state of pool members.
-		let init_free_balance_2 = Balances::free_balance(2);
-		let init_free_balance_3 = Balances::free_balance(3);
+		let init_stakeable_balance_2 = pallet_staking::asset::stakeable_balance::<Runtime>(&2);
+		let init_stakeable_balance_3 = pallet_staking::asset::stakeable_balance::<Runtime>(&3);
 
 		let pool_bonded_account = Pools::generate_bonded_account(1);
 
 		// creates a pool with 5 bonded, owned by 1.
 		assert_ok!(Pools::create(RuntimeOrigin::signed(1), 5, 1, 1, 1));
-		assert_eq!(locked_amount_for(pool_bonded_account), 5);
+		assert_eq!(staked_amount_for(pool_bonded_account), 5);
 
 		let init_tvl = TotalValueLocked::<Runtime>::get();
 
 		// 2 joins the pool.
 		assert_ok!(Pools::join(RuntimeOrigin::signed(2), 10, 1));
-		assert_eq!(locked_amount_for(pool_bonded_account), 15);
+		assert_eq!(staked_amount_for(pool_bonded_account), 15);
 
 		// 3 joins the pool.
 		assert_ok!(Pools::join(RuntimeOrigin::signed(3), 10, 1));
-		assert_eq!(locked_amount_for(pool_bonded_account), 25);
+		assert_eq!(staked_amount_for(pool_bonded_account), 25);
 
 		assert_eq!(TotalValueLocked::<Runtime>::get(), 25);
 
@@ -350,7 +350,7 @@ fn automatic_unbonding_pools() {
 		assert_ok!(Pools::unbond(RuntimeOrigin::signed(2), 2, 10));
 
 		// amount is still locked in the pool, needs to wait for unbonding period.
-		assert_eq!(locked_amount_for(pool_bonded_account), 25);
+		assert_eq!(staked_amount_for(pool_bonded_account), 25);
 
 		// max chunks in the ledger are now filled up (`MaxUnlockingChunks == 1`).
 		assert_eq!(unlocking_chunks_of(pool_bonded_account), 1);
@@ -372,8 +372,8 @@ fn automatic_unbonding_pools() {
 		assert_eq!(current_era(), 3);
 		System::reset_events();
 
-		let locked_before_withdraw_pool = locked_amount_for(pool_bonded_account);
-		assert_eq!(Balances::free_balance(pool_bonded_account), 26);
+		let staked_before_withdraw_pool = staked_amount_for(pool_bonded_account);
+		assert_eq!(pallet_staking::asset::stakeable_balance::<Runtime>(&pool_bonded_account), 26);
 
 		// now unbonding 3 will work, although the pool's ledger still has the unlocking chunks
 		// filled up.
@@ -391,20 +391,21 @@ fn automatic_unbonding_pools() {
 		);
 
 		// balance of the pool remains the same, it hasn't withdraw explicitly from the pool yet.
-		assert_eq!(Balances::free_balance(pool_bonded_account), 26);
+		assert_eq!(pallet_staking::asset::stakeable_balance::<Runtime>(&pool_bonded_account), 26);
 		// but the locked amount in the pool's account decreases due to the auto-withdraw:
-		assert_eq!(locked_before_withdraw_pool - 10, locked_amount_for(pool_bonded_account));
+		assert_eq!(staked_before_withdraw_pool - 10, staked_amount_for(pool_bonded_account));
 
 		// TVL correctly updated.
 		assert_eq!(TotalValueLocked::<Runtime>::get(), 25 - 10);
 
 		// however, note that the withdrawing from the pool still works for 2, the funds are taken
-		// from the pool's free balance.
-		assert_eq!(Balances::free_balance(pool_bonded_account), 26);
+		// from the pool's non staked balance.
+		assert_eq!(pallet_staking::asset::stakeable_balance::<Runtime>(&pool_bonded_account), 26);
+		assert_eq!(pallet_staking::asset::staked::<Runtime>(&pool_bonded_account), 15);
 		assert_ok!(Pools::withdraw_unbonded(RuntimeOrigin::signed(2), 2, 10));
-		assert_eq!(Balances::free_balance(pool_bonded_account), 16);
+		assert_eq!(pallet_staking::asset::stakeable_balance::<Runtime>(&pool_bonded_account), 16);
 
-		assert_eq!(Balances::free_balance(2), 20);
+		assert_eq!(pallet_staking::asset::stakeable_balance::<Runtime>(&2), 20);
 		assert_eq!(TotalValueLocked::<Runtime>::get(), 15);
 
 		// 3 cannot withdraw yet.
@@ -423,9 +424,15 @@ fn automatic_unbonding_pools() {
 		assert_ok!(Pools::withdraw_unbonded(RuntimeOrigin::signed(3), 3, 10));
 
 		// final conditions are the expected.
-		assert_eq!(Balances::free_balance(pool_bonded_account), 6); // 5 init bonded + ED
-		assert_eq!(Balances::free_balance(2), init_free_balance_2);
-		assert_eq!(Balances::free_balance(3), init_free_balance_3);
+		assert_eq!(pallet_staking::asset::stakeable_balance::<Runtime>(&pool_bonded_account), 6); // 5 init bonded + ED
+		assert_eq!(
+			pallet_staking::asset::stakeable_balance::<Runtime>(&2),
+			init_stakeable_balance_2
+		);
+		assert_eq!(
+			pallet_staking::asset::stakeable_balance::<Runtime>(&3),
+			init_stakeable_balance_3
+		);
 
 		assert_eq!(TotalValueLocked::<Runtime>::get(), init_tvl);
 	});
diff --git a/substrate/frame/election-provider-multi-phase/test-staking-e2e/src/mock.rs b/substrate/frame/election-provider-multi-phase/test-staking-e2e/src/mock.rs
index e45452c1ddf..f20e3983b09 100644
--- a/substrate/frame/election-provider-multi-phase/test-staking-e2e/src/mock.rs
+++ b/substrate/frame/election-provider-multi-phase/test-staking-e2e/src/mock.rs
@@ -915,9 +915,8 @@ pub(crate) fn set_minimum_election_score(
 	.map_err(|_| ())
 }
 
-pub(crate) fn locked_amount_for(account_id: AccountId) -> Balance {
-	let lock = pallet_balances::Locks::<Runtime>::get(account_id);
-	lock[0].amount
+pub(crate) fn staked_amount_for(account_id: AccountId) -> Balance {
+	pallet_staking::asset::staked::<Runtime>(&account_id)
 }
 
 pub(crate) fn staking_events() -> Vec<pallet_staking::Event<Runtime>> {
diff --git a/substrate/frame/fast-unstake/src/tests.rs b/substrate/frame/fast-unstake/src/tests.rs
index 77128872f28..7c11f381ca1 100644
--- a/substrate/frame/fast-unstake/src/tests.rs
+++ b/substrate/frame/fast-unstake/src/tests.rs
@@ -137,15 +137,16 @@ fn deregister_works() {
 	ExtBuilder::default().build_and_execute(|| {
 		ErasToCheckPerBlock::<T>::put(1);
 
-		assert_eq!(<T as Config>::Currency::reserved_balance(&1), 0);
+		// reserved balance prior to registering for fast unstake.
+		let pre_reserved = <T as Config>::Currency::reserved_balance(&1);
 
 		// Controller account registers for fast unstake.
 		assert_ok!(FastUnstake::register_fast_unstake(RuntimeOrigin::signed(1)));
-		assert_eq!(<T as Config>::Currency::reserved_balance(&1), Deposit::get());
+		assert_eq!(<T as Config>::Currency::reserved_balance(&1) - pre_reserved, Deposit::get());
 
 		// Controller then changes mind and deregisters.
 		assert_ok!(FastUnstake::deregister(RuntimeOrigin::signed(1)));
-		assert_eq!(<T as Config>::Currency::reserved_balance(&1), 0);
+		assert_eq!(<T as Config>::Currency::reserved_balance(&1) - pre_reserved, 0);
 
 		// Ensure stash no longer exists in the queue.
 		assert_eq!(Queue::<T>::get(1), None);
@@ -243,7 +244,8 @@ mod on_idle {
 			CurrentEra::<T>::put(BondingDuration::get());
 
 			// given
-			assert_eq!(<T as Config>::Currency::reserved_balance(&1), 0);
+			// reserved balance prior to registering for fast unstake.
+			let pre_reserved = <T as Config>::Currency::reserved_balance(&1);
 
 			assert_ok!(FastUnstake::register_fast_unstake(RuntimeOrigin::signed(1)));
 			assert_ok!(FastUnstake::register_fast_unstake(RuntimeOrigin::signed(3)));
@@ -251,7 +253,10 @@ mod on_idle {
 			assert_ok!(FastUnstake::register_fast_unstake(RuntimeOrigin::signed(7)));
 			assert_ok!(FastUnstake::register_fast_unstake(RuntimeOrigin::signed(9)));
 
-			assert_eq!(<T as Config>::Currency::reserved_balance(&1), Deposit::get());
+			assert_eq!(
+				<T as Config>::Currency::reserved_balance(&1) - pre_reserved,
+				Deposit::get()
+			);
 
 			assert_eq!(Queue::<T>::count(), 5);
 			assert_eq!(Head::<T>::get(), None);
@@ -279,6 +284,9 @@ mod on_idle {
 			// when
 			next_block(true);
 
+			// pre_reserve may change due to unstaked amount.
+			let pre_reserved = <T as Config>::Currency::reserved_balance(&1);
+
 			// then
 			assert_eq!(
 				Head::<T>::get(),
@@ -289,7 +297,7 @@ mod on_idle {
 			);
 			assert_eq!(Queue::<T>::count(), 3);
 
-			assert_eq!(<T as Config>::Currency::reserved_balance(&1), 0);
+			assert_eq!(<T as Config>::Currency::reserved_balance(&1) - pre_reserved, 0);
 
 			assert_eq!(
 				fast_unstake_events_since_last_call(),
diff --git a/substrate/frame/nomination-pools/benchmarking/src/inner.rs b/substrate/frame/nomination-pools/benchmarking/src/inner.rs
index 2a455942511..b0c8f3655a5 100644
--- a/substrate/frame/nomination-pools/benchmarking/src/inner.rs
+++ b/substrate/frame/nomination-pools/benchmarking/src/inner.rs
@@ -41,7 +41,7 @@ use sp_runtime::{
 	traits::{Bounded, StaticLookup, Zero},
 	Perbill,
 };
-use sp_staking::EraIndex;
+use sp_staking::{EraIndex, StakingUnchecked};
 // `frame_benchmarking::benchmarks!` macro needs this
 use pallet_nomination_pools::Call;
 
@@ -131,6 +131,8 @@ fn migrate_to_transfer_stake<T: Config>(pool_id: PoolId) {
 			)
 			.expect("member should have enough balance to transfer");
 		});
+
+	pallet_staking::Pallet::<T>::migrate_to_direct_staker(&pool_acc);
 }
 
 fn vote_to_balance<T: pallet_nomination_pools::Config>(
diff --git a/substrate/frame/nomination-pools/src/adapter.rs b/substrate/frame/nomination-pools/src/adapter.rs
index 272b3b60612..f125919dabf 100644
--- a/substrate/frame/nomination-pools/src/adapter.rs
+++ b/substrate/frame/nomination-pools/src/adapter.rs
@@ -460,6 +460,6 @@ impl<
 
 	#[cfg(feature = "runtime-benchmarks")]
 	fn remove_as_agent(pool: Pool<Self::AccountId>) {
-		Delegation::migrate_to_direct_staker(pool.into())
+		Delegation::force_kill_agent(pool.into())
 	}
 }
diff --git a/substrate/frame/offences/benchmarking/src/inner.rs b/substrate/frame/offences/benchmarking/src/inner.rs
index b16e5be653d..573114de074 100644
--- a/substrate/frame/offences/benchmarking/src/inner.rs
+++ b/substrate/frame/offences/benchmarking/src/inner.rs
@@ -20,7 +20,7 @@
 use alloc::{vec, vec::Vec};
 
 use frame_benchmarking::v1::{account, benchmarks};
-use frame_support::traits::{Currency, Get};
+use frame_support::traits::Get;
 use frame_system::{Config as SystemConfig, Pallet as System, RawOrigin};
 
 use sp_runtime::{
@@ -77,8 +77,7 @@ where
 }
 
 type LookupSourceOf<T> = <<T as SystemConfig>::Lookup as StaticLookup>::Source;
-type BalanceOf<T> =
-	<<T as StakingConfig>::Currency as Currency<<T as SystemConfig>::AccountId>>::Balance;
+type BalanceOf<T> = <T as StakingConfig>::CurrencyBalance;
 
 struct Offender<T: Config> {
 	pub controller: T::AccountId,
@@ -89,7 +88,7 @@ struct Offender<T: Config> {
 }
 
 fn bond_amount<T: Config>() -> BalanceOf<T> {
-	T::Currency::minimum_balance().saturating_mul(10_000u32.into())
+	pallet_staking::asset::existential_deposit::<T>().saturating_mul(10_000u32.into())
 }
 
 fn create_offender<T: Config>(n: u32, nominators: u32) -> Result<Offender<T>, &'static str> {
@@ -99,7 +98,7 @@ fn create_offender<T: Config>(n: u32, nominators: u32) -> Result<Offender<T>, &'
 	let amount = bond_amount::<T>();
 	// add twice as much balance to prevent the account from being killed.
 	let free_amount = amount.saturating_mul(2u32.into());
-	T::Currency::make_free_balance_be(&stash, free_amount);
+	pallet_staking::asset::set_stakeable_balance::<T>(&stash, free_amount);
 	Staking::<T>::bond(
 		RawOrigin::Signed(stash.clone()).into(),
 		amount,
@@ -116,7 +115,7 @@ fn create_offender<T: Config>(n: u32, nominators: u32) -> Result<Offender<T>, &'
 	for i in 0..nominators {
 		let nominator_stash: T::AccountId =
 			account("nominator stash", n * MAX_NOMINATORS + i, SEED);
-		T::Currency::make_free_balance_be(&nominator_stash, free_amount);
+		pallet_staking::asset::set_stakeable_balance::<T>(&nominator_stash, free_amount);
 
 		Staking::<T>::bond(
 			RawOrigin::Signed(nominator_stash.clone()).into(),
@@ -172,6 +171,14 @@ fn make_offenders<T: Config>(
 }
 
 benchmarks! {
+	where_clause {
+		where
+		<T as frame_system::Config>::RuntimeEvent: TryInto<pallet_staking::Event<T>>,
+		<T as frame_system::Config>::RuntimeEvent: TryInto<pallet_balances::Event<T>>,
+		<T as frame_system::Config>::RuntimeEvent: TryInto<pallet_offences::Event>,
+		<T as frame_system::Config>::RuntimeEvent: TryInto<frame_system::Event<T>>,
+	}
+
 	report_offence_grandpa {
 		let n in 0 .. MAX_NOMINATORS.min(MaxNominationsOf::<T>::get());
 
@@ -196,17 +203,19 @@ benchmarks! {
 		let _ = Offences::<T>::report_offence(reporters, offence);
 	}
 	verify {
-		// make sure that all slashes have been applied
 		#[cfg(test)]
-		assert_eq!(
-			System::<T>::event_count(), 0
-			+ 1 // offence
-			+ 3 // reporter (reward + endowment)
-			+ 1 // offenders reported
-			+ 3 // offenders slashed
-			+ 1 // offenders chilled
-			+ 3 * n // nominators slashed
-		);
+		{
+			// make sure that all slashes have been applied
+			// (n nominators + one validator) * (slashed + unlocked) + deposit to reporter + reporter
+			// account endowed + some funds rescinded from issuance.
+			assert_eq!(System::<T>::read_events_for_pallet::<pallet_balances::Event<T>>().len(), 2 * (n + 1) as usize + 3);
+			// (n nominators + one validator) * slashed + Slash Reported
+			assert_eq!(System::<T>::read_events_for_pallet::<pallet_staking::Event<T>>().len(), 1 * (n + 1) as usize + 1);
+			// offence
+			assert_eq!(System::<T>::read_events_for_pallet::<pallet_offences::Event>().len(), 1);
+			// reporter new account
+			assert_eq!(System::<T>::read_events_for_pallet::<frame_system::Event<T>>().len(), 1);
+		}
 	}
 
 	report_offence_babe {
@@ -233,17 +242,19 @@ benchmarks! {
 		let _ = Offences::<T>::report_offence(reporters, offence);
 	}
 	verify {
-		// make sure that all slashes have been applied
 		#[cfg(test)]
-		assert_eq!(
-			System::<T>::event_count(), 0
-			+ 1 // offence
-			+ 3 // reporter (reward + endowment)
-			+ 1 // offenders reported
-			+ 3 // offenders slashed
-			+ 1 // offenders chilled
-			+ 3 * n // nominators slashed
-		);
+		{
+			// make sure that all slashes have been applied
+			// (n nominators + one validator) * (slashed + unlocked) + deposit to reporter + reporter
+			// account endowed + some funds rescinded from issuance.
+			assert_eq!(System::<T>::read_events_for_pallet::<pallet_balances::Event<T>>().len(), 2 * (n + 1) as usize + 3);
+			// (n nominators + one validator) * slashed + Slash Reported
+			assert_eq!(System::<T>::read_events_for_pallet::<pallet_staking::Event<T>>().len(), 1 * (n + 1) as usize + 1);
+			// offence
+			assert_eq!(System::<T>::read_events_for_pallet::<pallet_offences::Event>().len(), 1);
+			// reporter new account
+			assert_eq!(System::<T>::read_events_for_pallet::<frame_system::Event<T>>().len(), 1);
+		}
 	}
 
 	impl_benchmark_test_suite!(Pallet, crate::mock::new_test_ext(), crate::mock::Test);
diff --git a/substrate/frame/root-offences/src/tests.rs b/substrate/frame/root-offences/src/tests.rs
index f96884d750d..289bb708efb 100644
--- a/substrate/frame/root-offences/src/tests.rs
+++ b/substrate/frame/root-offences/src/tests.rs
@@ -17,7 +17,8 @@
 
 use super::*;
 use frame_support::{assert_err, assert_ok};
-use mock::{active_era, start_session, Balances, ExtBuilder, RootOffences, RuntimeOrigin, System};
+use mock::{active_era, start_session, ExtBuilder, RootOffences, RuntimeOrigin, System, Test as T};
+use pallet_staking::asset;
 
 #[test]
 fn create_offence_fails_given_signed_origin() {
@@ -35,18 +36,18 @@ fn create_offence_works_given_root_origin() {
 
 		assert_eq!(active_era(), 0);
 
-		assert_eq!(Balances::free_balance(11), 1000);
+		assert_eq!(asset::staked::<T>(&11), 1000);
 
 		let offenders = [(11, Perbill::from_percent(50))].to_vec();
 		assert_ok!(RootOffences::create_offence(RuntimeOrigin::root(), offenders.clone()));
 
 		System::assert_last_event(Event::OffenceCreated { offenders }.into());
 		// the slash should be applied right away.
-		assert_eq!(Balances::free_balance(11), 500);
+		assert_eq!(asset::staked::<T>(&11), 500);
 
 		// the other validator should keep their balance, because we only created
 		// an offences for the first validator.
-		assert_eq!(Balances::free_balance(21), 1000);
+		assert_eq!(asset::staked::<T>(&21), 1000);
 	})
 }
 
@@ -58,7 +59,7 @@ fn create_offence_wont_slash_non_active_validators() {
 		assert_eq!(active_era(), 0);
 
 		// 31 is not an active validator.
-		assert_eq!(Balances::free_balance(31), 500);
+		assert_eq!(asset::staked::<T>(&31), 500);
 
 		let offenders = [(31, Perbill::from_percent(20)), (11, Perbill::from_percent(20))].to_vec();
 		assert_ok!(RootOffences::create_offence(RuntimeOrigin::root(), offenders.clone()));
@@ -66,10 +67,10 @@ fn create_offence_wont_slash_non_active_validators() {
 		System::assert_last_event(Event::OffenceCreated { offenders }.into());
 
 		// so 31 didn't get slashed.
-		assert_eq!(Balances::free_balance(31), 500);
+		assert_eq!(asset::staked::<T>(&31), 500);
 
 		// but 11 is an active validator so they got slashed.
-		assert_eq!(Balances::free_balance(11), 800);
+		assert_eq!(asset::staked::<T>(&11), 800);
 	})
 }
 
@@ -81,7 +82,7 @@ fn create_offence_wont_slash_idle() {
 		assert_eq!(active_era(), 0);
 
 		// 41 is idle.
-		assert_eq!(Balances::free_balance(41), 1000);
+		assert_eq!(asset::staked::<T>(&41), 1000);
 
 		let offenders = [(41, Perbill::from_percent(50))].to_vec();
 		assert_ok!(RootOffences::create_offence(RuntimeOrigin::root(), offenders.clone()));
@@ -89,6 +90,6 @@ fn create_offence_wont_slash_idle() {
 		System::assert_last_event(Event::OffenceCreated { offenders }.into());
 
 		// 41 didn't get slashed.
-		assert_eq!(Balances::free_balance(41), 1000);
+		assert_eq!(asset::staked::<T>(&41), 1000);
 	})
 }
diff --git a/substrate/frame/staking/src/asset.rs b/substrate/frame/staking/src/asset.rs
new file mode 100644
index 00000000000..23368b1f8fc
--- /dev/null
+++ b/substrate/frame/staking/src/asset.rs
@@ -0,0 +1,125 @@
+// This file is part of Substrate.
+
+// Copyright (C) Parity Technologies (UK) Ltd.
+// SPDX-License-Identifier: Apache-2.0
+
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// 	http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+//! Contains all the interactions with [`Config::Currency`] to manipulate the underlying staking
+//! asset.
+
+use frame_support::traits::{Currency, InspectLockableCurrency, LockableCurrency};
+
+use crate::{BalanceOf, Config, NegativeImbalanceOf, PositiveImbalanceOf};
+
+/// Existential deposit for the chain.
+pub fn existential_deposit<T: Config>() -> BalanceOf<T> {
+	T::Currency::minimum_balance()
+}
+
+/// Total issuance of the chain.
+pub fn total_issuance<T: Config>() -> BalanceOf<T> {
+	T::Currency::total_issuance()
+}
+
+/// Total balance of `who`. Includes both, free and reserved.
+pub fn total_balance<T: Config>(who: &T::AccountId) -> BalanceOf<T> {
+	T::Currency::total_balance(who)
+}
+
+/// Stakeable balance of `who`.
+///
+/// This includes balance free to stake along with any balance that is already staked.
+pub fn stakeable_balance<T: Config>(who: &T::AccountId) -> BalanceOf<T> {
+	T::Currency::free_balance(who)
+}
+
+/// Balance of `who` that is currently at stake.
+///
+/// The staked amount is locked and cannot be transferred out of `who`s account.
+pub fn staked<T: Config>(who: &T::AccountId) -> BalanceOf<T> {
+	T::Currency::balance_locked(crate::STAKING_ID, who)
+}
+
+/// Set balance that can be staked for `who`.
+///
+/// This includes any balance that is already staked.
+#[cfg(any(test, feature = "runtime-benchmarks"))]
+pub fn set_stakeable_balance<T: Config>(who: &T::AccountId, value: BalanceOf<T>) {
+	T::Currency::make_free_balance_be(who, value);
+}
+
+/// Update `amount` at stake for `who`.
+///
+/// Overwrites the existing stake amount. If passed amount is lower than the existing stake, the
+/// difference is unlocked.
+pub fn update_stake<T: Config>(who: &T::AccountId, amount: BalanceOf<T>) {
+	T::Currency::set_lock(
+		crate::STAKING_ID,
+		who,
+		amount,
+		frame_support::traits::WithdrawReasons::all(),
+	);
+}
+
+/// Kill the stake of `who`.
+///
+/// All locked amount is unlocked.
+pub fn kill_stake<T: Config>(who: &T::AccountId) {
+	T::Currency::remove_lock(crate::STAKING_ID, who);
+}
+
+/// Slash the value from `who`.
+///
+/// A negative imbalance is returned which can be resolved to deposit the slashed value.
+pub fn slash<T: Config>(
+	who: &T::AccountId,
+	value: BalanceOf<T>,
+) -> (NegativeImbalanceOf<T>, BalanceOf<T>) {
+	T::Currency::slash(who, value)
+}
+
+/// Mint `value` into an existing account `who`.
+///
+/// This does not increase the total issuance.
+pub fn mint_existing<T: Config>(
+	who: &T::AccountId,
+	value: BalanceOf<T>,
+) -> Option<PositiveImbalanceOf<T>> {
+	T::Currency::deposit_into_existing(who, value).ok()
+}
+
+/// Mint reward and create account for `who` if it does not exist.
+///
+/// This does not increase the total issuance.
+pub fn mint_creating<T: Config>(who: &T::AccountId, value: BalanceOf<T>) -> PositiveImbalanceOf<T> {
+	T::Currency::deposit_creating(who, value)
+}
+
+/// Deposit newly issued or slashed `value` into `who`.
+pub fn deposit_slashed<T: Config>(who: &T::AccountId, value: NegativeImbalanceOf<T>) {
+	T::Currency::resolve_creating(who, value)
+}
+
+/// Issue `value` increasing total issuance.
+///
+/// Creates a negative imbalance.
+pub fn issue<T: Config>(value: BalanceOf<T>) -> NegativeImbalanceOf<T> {
+	T::Currency::issue(value)
+}
+
+/// Burn the amount from the total issuance.
+#[cfg(feature = "runtime-benchmarks")]
+pub fn burn<T: Config>(amount: BalanceOf<T>) -> PositiveImbalanceOf<T> {
+	T::Currency::burn(amount)
+}
diff --git a/substrate/frame/staking/src/benchmarking.rs b/substrate/frame/staking/src/benchmarking.rs
index 1f8580d7a3e..a25085a1803 100644
--- a/substrate/frame/staking/src/benchmarking.rs
+++ b/substrate/frame/staking/src/benchmarking.rs
@@ -18,7 +18,7 @@
 //! Staking pallet benchmarking.
 
 use super::*;
-use crate::{ConfigOp, Pallet as Staking};
+use crate::{asset, ConfigOp, Pallet as Staking};
 use testing_utils::*;
 
 use codec::Decode;
@@ -26,7 +26,7 @@ use frame_election_provider_support::{bounds::DataProviderBounds, SortedListProv
 use frame_support::{
 	pallet_prelude::*,
 	storage::bounded_vec::BoundedVec,
-	traits::{Currency, Get, Imbalance, UnfilteredDispatchable},
+	traits::{Get, Imbalance, UnfilteredDispatchable},
 };
 use sp_runtime::{
 	traits::{Bounded, One, StaticLookup, TrailingZeroInput, Zero},
@@ -132,7 +132,7 @@ pub fn create_validator_with_nominators<T: Config>(
 	ErasRewardPoints::<T>::insert(current_era, reward);
 
 	// Create reward pool
-	let total_payout = T::Currency::minimum_balance()
+	let total_payout = asset::existential_deposit::<T>()
 		.saturating_mul(upper_bound.into())
 		.saturating_mul(1000u32.into());
 	<ErasValidatorReward<T>>::insert(current_era, total_payout);
@@ -167,7 +167,7 @@ impl<T: Config> ListScenario<T> {
 		ensure!(!origin_weight.is_zero(), "origin weight must be greater than 0");
 
 		// burn the entire issuance.
-		let i = T::Currency::burn(T::Currency::total_issuance());
+		let i = asset::burn::<T>(asset::total_issuance::<T>());
 		core::mem::forget(i);
 
 		// create accounts with the origin weight
@@ -197,7 +197,7 @@ impl<T: Config> ListScenario<T> {
 		let dest_weight_as_vote =
 			T::VoterList::score_update_worst_case(&origin_stash1, is_increase);
 
-		let total_issuance = T::Currency::total_issuance();
+		let total_issuance = asset::total_issuance::<T>();
 
 		let dest_weight =
 			T::CurrencyToVote::to_currency(dest_weight_as_vote as u128, total_issuance);
@@ -223,7 +223,7 @@ benchmarks! {
 	bond {
 		let stash = create_funded_user::<T>("stash", USER_SEED, 100);
 		let reward_destination = RewardDestination::Staked;
-		let amount = T::Currency::minimum_balance() * 10u32.into();
+		let amount = asset::existential_deposit::<T>() * 10u32.into();
 		whitelist_account!(stash);
 	}: _(RawOrigin::Signed(stash.clone()), amount, reward_destination)
 	verify {
@@ -235,7 +235,7 @@ benchmarks! {
 		// clean up any existing state.
 		clear_validators_and_nominators::<T>();
 
-		let origin_weight = MinNominatorBond::<T>::get().max(T::Currency::minimum_balance());
+		let origin_weight = MinNominatorBond::<T>::get().max(asset::existential_deposit::<T>());
 
 		// setup the worst case list scenario.
 
@@ -249,7 +249,7 @@ benchmarks! {
 		let original_bonded: BalanceOf<T>
 			= Ledger::<T>::get(&controller).map(|l| l.active).ok_or("ledger not created after")?;
 
-		let _ = T::Currency::deposit_into_existing(&stash, max_additional).unwrap();
+		let _ = asset::mint_existing::<T>(&stash, max_additional).unwrap();
 
 		whitelist_account!(stash);
 	}: _(RawOrigin::Signed(stash), max_additional)
@@ -264,7 +264,7 @@ benchmarks! {
 		clear_validators_and_nominators::<T>();
 
 		// setup the worst case list scenario.
-		let total_issuance = T::Currency::total_issuance();
+		let total_issuance = asset::total_issuance::<T>();
 		// the weight the nominator will start at. The value used here is expected to be
 		// significantly higher than the first position in a list (e.g. the first bag threshold).
 		let origin_weight = BalanceOf::<T>::try_from(952_994_955_240_703u128)
@@ -292,7 +292,7 @@ benchmarks! {
 		let s in 0 .. MAX_SPANS;
 		let (stash, controller) = create_stash_controller::<T>(0, 100, RewardDestination::Staked)?;
 		add_slashing_spans::<T>(&stash, s);
-		let amount = T::Currency::minimum_balance() * 5u32.into(); // Half of total
+		let amount = asset::existential_deposit::<T>() * 5u32.into(); // Half of total
 		Staking::<T>::unbond(RawOrigin::Signed(controller.clone()).into(), amount)?;
 		CurrentEra::<T>::put(EraIndex::max_value());
 		let ledger = Ledger::<T>::get(&controller).ok_or("ledger not created before")?;
@@ -312,7 +312,7 @@ benchmarks! {
 		// clean up any existing state.
 		clear_validators_and_nominators::<T>();
 
-		let origin_weight = MinNominatorBond::<T>::get().max(T::Currency::minimum_balance());
+		let origin_weight = MinNominatorBond::<T>::get().max(asset::existential_deposit::<T>());
 
 		// setup a worst case list scenario. Note that we don't care about the setup of the
 		// destination position because we are doing a removal from the list but no insert.
@@ -322,7 +322,7 @@ benchmarks! {
 		add_slashing_spans::<T>(&stash, s);
 		assert!(T::VoterList::contains(&stash));
 
-		let ed = T::Currency::minimum_balance();
+		let ed = asset::existential_deposit::<T>();
 		let mut ledger = Ledger::<T>::get(&controller).unwrap();
 		ledger.active = ed - One::one();
 		Ledger::<T>::insert(&controller, ledger);
@@ -422,7 +422,7 @@ benchmarks! {
 		// clean up any existing state.
 		clear_validators_and_nominators::<T>();
 
-		let origin_weight = MinNominatorBond::<T>::get().max(T::Currency::minimum_balance());
+		let origin_weight = MinNominatorBond::<T>::get().max(asset::existential_deposit::<T>());
 
 		// setup a worst case list scenario. Note we don't care about the destination position, because
 		// we are just doing an insert into the origin position.
@@ -448,7 +448,7 @@ benchmarks! {
 		// clean up any existing state.
 		clear_validators_and_nominators::<T>();
 
-		let origin_weight = MinNominatorBond::<T>::get().max(T::Currency::minimum_balance());
+		let origin_weight = MinNominatorBond::<T>::get().max(asset::existential_deposit::<T>());
 
 		// setup a worst case list scenario. Note that we don't care about the setup of the
 		// destination position because we are doing a removal from the list but no insert.
@@ -564,7 +564,7 @@ benchmarks! {
 		// Clean up any existing state.
 		clear_validators_and_nominators::<T>();
 
-		let origin_weight = MinNominatorBond::<T>::get().max(T::Currency::minimum_balance());
+		let origin_weight = MinNominatorBond::<T>::get().max(asset::existential_deposit::<T>());
 
 		// setup a worst case list scenario. Note that we don't care about the setup of the
 		// destination position because we are doing a removal from the list but no insert.
@@ -611,21 +611,21 @@ benchmarks! {
 		<ErasValidatorPrefs<T>>::insert(current_era, validator.clone(), <Staking<T>>::validators(&validator));
 
 		let caller = whitelisted_caller();
-		let balance_before = T::Currency::free_balance(&validator);
+		let balance_before = asset::stakeable_balance::<T>(&validator);
 		let mut nominator_balances_before = Vec::new();
 		for (stash, _) in &nominators {
-			let balance = T::Currency::free_balance(stash);
+			let balance = asset::stakeable_balance::<T>(stash);
 			nominator_balances_before.push(balance);
 		}
 	}: payout_stakers(RawOrigin::Signed(caller), validator.clone(), current_era)
 	verify {
-		let balance_after = T::Currency::free_balance(&validator);
+		let balance_after = asset::stakeable_balance::<T>(&validator);
 		ensure!(
 			balance_before < balance_after,
 			"Balance of validator stash should have increased after payout.",
 		);
 		for ((stash, _), balance_before) in nominators.iter().zip(nominator_balances_before.iter()) {
-			let balance_after = T::Currency::free_balance(stash);
+			let balance_after = asset::stakeable_balance::<T>(stash);
 			ensure!(
 				balance_before < &balance_after,
 				"Balance of nominator stash should have increased after payout.",
@@ -640,7 +640,7 @@ benchmarks! {
 		clear_validators_and_nominators::<T>();
 
 		let origin_weight = MinNominatorBond::<T>::get()
-			.max(T::Currency::minimum_balance())
+			.max(asset::existential_deposit::<T>())
 			// we use 100 to play friendly with the list threshold values in the mock
 			.max(100u32.into());
 
@@ -686,7 +686,7 @@ benchmarks! {
 		// clean up any existing state.
 		clear_validators_and_nominators::<T>();
 
-		let origin_weight = MinNominatorBond::<T>::get().max(T::Currency::minimum_balance());
+		let origin_weight = MinNominatorBond::<T>::get().max(asset::existential_deposit::<T>());
 
 		// setup a worst case list scenario. Note that we don't care about the setup of the
 		// destination position because we are doing a removal from the list but no insert.
@@ -697,7 +697,7 @@ benchmarks! {
 		add_slashing_spans::<T>(&stash, s);
 		let l = StakingLedger::<T>::new(
 			stash.clone(),
-			T::Currency::minimum_balance() - One::one(),
+			asset::existential_deposit::<T>() - One::one(),
 		);
 		Ledger::<T>::insert(&controller, l);
 
@@ -764,7 +764,7 @@ benchmarks! {
 		ErasRewardPoints::<T>::insert(current_era, reward);
 
 		// Create reward pool
-		let total_payout = T::Currency::minimum_balance() * 1000u32.into();
+		let total_payout = asset::existential_deposit::<T>() * 1000u32.into();
 		<ErasValidatorReward<T>>::insert(current_era, total_payout);
 
 		let caller: T::AccountId = whitelisted_caller();
@@ -793,8 +793,8 @@ benchmarks! {
 			staking_ledger.unlocking.try_push(unlock_chunk.clone()).unwrap();
 		}
 		Ledger::<T>::insert(controller, staking_ledger);
-		let slash_amount = T::Currency::minimum_balance() * 10u32.into();
-		let balance_before = T::Currency::free_balance(&stash);
+		let slash_amount = asset::existential_deposit::<T>() * 10u32.into();
+		let balance_before = asset::stakeable_balance::<T>(&stash);
 	}: {
 		crate::slashing::do_slash::<T>(
 			&stash,
@@ -804,7 +804,7 @@ benchmarks! {
 			EraIndex::zero()
 		);
 	} verify {
-		let balance_after = T::Currency::free_balance(&stash);
+		let balance_after = asset::stakeable_balance::<T>(&stash);
 		assert!(balance_before > balance_after);
 	}
 
@@ -890,7 +890,7 @@ benchmarks! {
 		// clean up any existing state.
 		clear_validators_and_nominators::<T>();
 
-		let origin_weight = MinNominatorBond::<T>::get().max(T::Currency::minimum_balance());
+		let origin_weight = MinNominatorBond::<T>::get().max(asset::existential_deposit::<T>());
 
 		// setup a worst case list scenario. Note that we don't care about the setup of the
 		// destination position because we are doing a removal from the list but no insert.
@@ -972,7 +972,7 @@ benchmarks! {
 #[cfg(test)]
 mod tests {
 	use super::*;
-	use crate::mock::{Balances, ExtBuilder, RuntimeOrigin, Staking, Test};
+	use crate::mock::{ExtBuilder, RuntimeOrigin, Staking, Test};
 	use frame_support::assert_ok;
 
 	#[test]
@@ -1019,16 +1019,17 @@ mod tests {
 
 			let current_era = CurrentEra::<Test>::get().unwrap();
 
-			let original_free_balance = Balances::free_balance(&validator_stash);
+			let original_stakeable_balance = asset::stakeable_balance::<Test>(&validator_stash);
 			assert_ok!(Staking::payout_stakers_by_page(
 				RuntimeOrigin::signed(1337),
 				validator_stash,
 				current_era,
 				0
 			));
-			let new_free_balance = Balances::free_balance(&validator_stash);
+			let new_stakeable_balance = asset::stakeable_balance::<Test>(&validator_stash);
 
-			assert!(original_free_balance < new_free_balance);
+			// reward increases stakeable balance
+			assert!(original_stakeable_balance < new_stakeable_balance);
 		});
 	}
 
diff --git a/substrate/frame/staking/src/ledger.rs b/substrate/frame/staking/src/ledger.rs
index dc4b4fc326b..ac3be04cf60 100644
--- a/substrate/frame/staking/src/ledger.rs
+++ b/substrate/frame/staking/src/ledger.rs
@@ -31,15 +31,12 @@
 //! performed through the methods exposed by the [`StakingLedger`] implementation in order to ensure
 //! state consistency.
 
-use frame_support::{
-	defensive, ensure,
-	traits::{Defensive, LockableCurrency},
-};
+use frame_support::{defensive, ensure, traits::Defensive};
 use sp_staking::{StakingAccount, StakingInterface};
 
 use crate::{
-	BalanceOf, Bonded, Config, Error, Ledger, Pallet, Payee, RewardDestination, StakingLedger,
-	VirtualStakers, STAKING_ID,
+	asset, BalanceOf, Bonded, Config, Error, Ledger, Pallet, Payee, RewardDestination,
+	StakingLedger, VirtualStakers,
 };
 
 #[cfg(any(feature = "runtime-benchmarks", test))]
@@ -190,12 +187,7 @@ impl<T: Config> StakingLedger<T> {
 		// We skip locking virtual stakers.
 		if !Pallet::<T>::is_virtual_staker(&self.stash) {
 			// for direct stakers, update lock on stash based on ledger.
-			T::Currency::set_lock(
-				STAKING_ID,
-				&self.stash,
-				self.total,
-				frame_support::traits::WithdrawReasons::all(),
-			);
+			asset::update_stake::<T>(&self.stash, self.total);
 		}
 
 		Ledger::<T>::insert(
@@ -269,7 +261,7 @@ impl<T: Config> StakingLedger<T> {
 			// kill virtual staker if it exists.
 			if <VirtualStakers<T>>::take(&stash).is_none() {
 				// if not virtual staker, clear locks.
-				T::Currency::remove_lock(STAKING_ID, &ledger.stash);
+				asset::kill_stake::<T>(&ledger.stash);
 			}
 
 			Ok(())
diff --git a/substrate/frame/staking/src/lib.rs b/substrate/frame/staking/src/lib.rs
index 9e59cbd3d0c..19d999109d8 100644
--- a/substrate/frame/staking/src/lib.rs
+++ b/substrate/frame/staking/src/lib.rs
@@ -295,6 +295,7 @@ pub(crate) mod mock;
 #[cfg(test)]
 mod tests;
 
+pub mod asset;
 pub mod election_size_tracker;
 pub mod inflation;
 pub mod ledger;
diff --git a/substrate/frame/staking/src/pallet/impls.rs b/substrate/frame/staking/src/pallet/impls.rs
index 2df3bc084eb..6c4fe8140e8 100644
--- a/substrate/frame/staking/src/pallet/impls.rs
+++ b/substrate/frame/staking/src/pallet/impls.rs
@@ -27,8 +27,8 @@ use frame_support::{
 	dispatch::WithPostDispatchInfo,
 	pallet_prelude::*,
 	traits::{
-		Currency, Defensive, DefensiveSaturating, EstimateNextNewSession, Get, Imbalance,
-		InspectLockableCurrency, Len, LockableCurrency, OnUnbalanced, TryCollect, UnixTime,
+		Defensive, DefensiveSaturating, EstimateNextNewSession, Get, Imbalance, Len, OnUnbalanced,
+		TryCollect, UnixTime,
 	},
 	weights::Weight,
 };
@@ -50,7 +50,7 @@ use sp_staking::{
 };
 
 use crate::{
-	election_size_tracker::StaticTracker, log, slashing, weights::WeightInfo, ActiveEraInfo,
+	asset, election_size_tracker::StaticTracker, log, slashing, weights::WeightInfo, ActiveEraInfo,
 	BalanceOf, EraInfo, EraPayout, Exposure, ExposureOf, Forcing, IndividualExposure,
 	LedgerIntegrityState, MaxNominationsOf, MaxWinnersOf, Nominations, NominationsQuota,
 	PositiveImbalanceOf, RewardDestination, SessionInterface, StakingLedger, ValidatorPrefs,
@@ -96,7 +96,7 @@ impl<T: Config> Pallet<T> {
 	pub(crate) fn inspect_bond_state(
 		stash: &T::AccountId,
 	) -> Result<LedgerIntegrityState, Error<T>> {
-		let lock = T::Currency::balance_locked(crate::STAKING_ID, &stash);
+		let lock = asset::staked::<T>(&stash);
 
 		let controller = <Bonded<T>>::get(stash).ok_or_else(|| {
 			if lock == Zero::zero() {
@@ -142,7 +142,7 @@ impl<T: Config> Pallet<T> {
 	pub fn weight_of_fn() -> Box<dyn Fn(&T::AccountId) -> VoteWeight> {
 		// NOTE: changing this to unboxed `impl Fn(..)` return type and the pallet will still
 		// compile, while some types in mock fail to resolve.
-		let issuance = T::Currency::total_issuance();
+		let issuance = asset::total_issuance::<T>();
 		Box::new(move |who: &T::AccountId| -> VoteWeight {
 			Self::slashable_balance_of_vote_weight(who, issuance)
 		})
@@ -150,7 +150,7 @@ impl<T: Config> Pallet<T> {
 
 	/// Same as `weight_of_fn`, but made for one time use.
 	pub fn weight_of(who: &T::AccountId) -> VoteWeight {
-		let issuance = T::Currency::total_issuance();
+		let issuance = asset::total_issuance::<T>();
 		Self::slashable_balance_of_vote_weight(who, issuance)
 	}
 
@@ -164,7 +164,7 @@ impl<T: Config> Pallet<T> {
 		} else {
 			// additional amount or actual balance of stash whichever is lower.
 			additional.min(
-				T::Currency::free_balance(stash)
+				asset::stakeable_balance::<T>(stash)
 					.checked_sub(&ledger.total)
 					.ok_or(ArithmeticError::Overflow)?,
 			)
@@ -173,7 +173,7 @@ impl<T: Config> Pallet<T> {
 		ledger.total = ledger.total.checked_add(&extra).ok_or(ArithmeticError::Overflow)?;
 		ledger.active = ledger.active.checked_add(&extra).ok_or(ArithmeticError::Overflow)?;
 		// last check: the new active amount of ledger must be more than ED.
-		ensure!(ledger.active >= T::Currency::minimum_balance(), Error::<T>::InsufficientBond);
+		ensure!(ledger.active >= asset::existential_deposit::<T>(), Error::<T>::InsufficientBond);
 
 		// NOTE: ledger must be updated prior to calling `Self::weight_of`.
 		ledger.update()?;
@@ -198,7 +198,7 @@ impl<T: Config> Pallet<T> {
 		}
 		let new_total = ledger.total;
 
-		let ed = T::Currency::minimum_balance();
+		let ed = asset::existential_deposit::<T>();
 		let used_weight =
 			if ledger.unlocking.is_empty() && (ledger.active < ed || ledger.active.is_zero()) {
 				// This account must have called `unbond()` with some value that caused the active
@@ -414,12 +414,12 @@ impl<T: Config> Pallet<T> {
 		let dest = Self::payee(StakingAccount::Stash(stash.clone()))?;
 
 		let maybe_imbalance = match dest {
-			RewardDestination::Stash => T::Currency::deposit_into_existing(stash, amount).ok(),
+			RewardDestination::Stash => asset::mint_existing::<T>(stash, amount),
 			RewardDestination::Staked => Self::ledger(Stash(stash.clone()))
 				.and_then(|mut ledger| {
 					ledger.active += amount;
 					ledger.total += amount;
-					let r = T::Currency::deposit_into_existing(stash, amount).ok();
+					let r = asset::mint_existing::<T>(stash, amount);
 
 					let _ = ledger
 						.update()
@@ -429,7 +429,7 @@ impl<T: Config> Pallet<T> {
 				})
 				.unwrap_or_default(),
 			RewardDestination::Account(ref dest_account) =>
-				Some(T::Currency::deposit_creating(&dest_account, amount)),
+				Some(asset::mint_creating::<T>(&dest_account, amount)),
 			RewardDestination::None => None,
 			#[allow(deprecated)]
 			RewardDestination::Controller => Self::bonded(stash)
@@ -437,7 +437,7 @@ impl<T: Config> Pallet<T> {
 						defensive!("Paying out controller as reward destination which is deprecated and should be migrated.");
 						// This should never happen once payees with a `Controller` variant have been migrated.
 						// But if it does, just pay the controller account.
-						T::Currency::deposit_creating(&controller, amount)
+						asset::mint_creating::<T>(&controller, amount)
 		}),
 		};
 		maybe_imbalance.map(|imbalance| (imbalance, dest))
@@ -576,7 +576,7 @@ impl<T: Config> Pallet<T> {
 			let era_duration = (now_as_millis_u64.defensive_saturating_sub(active_era_start))
 				.saturated_into::<u64>();
 			let staked = Self::eras_total_stake(&active_era.index);
-			let issuance = T::Currency::total_issuance();
+			let issuance = asset::total_issuance::<T>();
 
 			let (validator_payout, remainder) =
 				T::EraPayout::era_payout(staked, issuance, era_duration);
@@ -597,7 +597,7 @@ impl<T: Config> Pallet<T> {
 
 			// Set ending era reward.
 			<ErasValidatorReward<T>>::insert(&active_era.index, validator_payout);
-			T::RewardRemainder::on_unbalanced(T::Currency::issue(remainder));
+			T::RewardRemainder::on_unbalanced(asset::issue::<T>(remainder));
 
 			// Clear disabled validators.
 			<DisabledValidators<T>>::kill();
@@ -748,7 +748,7 @@ impl<T: Config> Pallet<T> {
 	fn collect_exposures(
 		supports: BoundedSupportsOf<T::ElectionProvider>,
 	) -> BoundedVec<(T::AccountId, Exposure<T::AccountId, BalanceOf<T>>), MaxWinnersOf<T>> {
-		let total_issuance = T::Currency::total_issuance();
+		let total_issuance = asset::total_issuance::<T>();
 		let to_currency = |e: frame_election_provider_support::ExtendedBalance| {
 			T::CurrencyToVote::to_currency(e, total_issuance)
 		};
@@ -1581,7 +1581,7 @@ impl<T: Config> ScoreProvider<T::AccountId> for Pallet<T> {
 		// also, we play a trick to make sure that a issuance based-`CurrencyToVote` behaves well:
 		// This will make sure that total issuance is zero, thus the currency to vote will be a 1-1
 		// conversion.
-		let imbalance = T::Currency::burn(T::Currency::total_issuance());
+		let imbalance = asset::burn::<T>(asset::total_issuance::<T>());
 		// kinda ugly, but gets the job done. The fact that this works here is a HUGE exception.
 		// Don't try this pattern in other places.
 		core::mem::forget(imbalance);
@@ -1919,7 +1919,7 @@ impl<T: Config> StakingInterface for Pallet<T> {
 
 impl<T: Config> sp_staking::StakingUnchecked for Pallet<T> {
 	fn migrate_to_virtual_staker(who: &Self::AccountId) {
-		T::Currency::remove_lock(crate::STAKING_ID, who);
+		asset::kill_stake::<T>(who);
 		VirtualStakers::<T>::insert(who, ());
 	}
 
@@ -1956,12 +1956,7 @@ impl<T: Config> sp_staking::StakingUnchecked for Pallet<T> {
 	fn migrate_to_direct_staker(who: &Self::AccountId) {
 		assert!(VirtualStakers::<T>::contains_key(who));
 		let ledger = StakingLedger::<T>::get(Stash(who.clone())).unwrap();
-		T::Currency::set_lock(
-			crate::STAKING_ID,
-			who,
-			ledger.total,
-			frame_support::traits::WithdrawReasons::all(),
-		);
+		asset::update_stake::<T>(who, ledger.total);
 		VirtualStakers::<T>::remove(who);
 	}
 }
@@ -2097,7 +2092,7 @@ impl<T: Config> Pallet<T> {
 				// ensure locks consistency.
 				if VirtualStakers::<T>::contains_key(stash.clone()) {
 					ensure!(
-						T::Currency::balance_locked(crate::STAKING_ID, &stash) == Zero::zero(),
+						asset::staked::<T>(&stash) == Zero::zero(),
 						"virtual stakers should not have any locked balance"
 					);
 					ensure!(
diff --git a/substrate/frame/staking/src/pallet/mod.rs b/substrate/frame/staking/src/pallet/mod.rs
index 8a4482f52ad..28aa4f89b62 100644
--- a/substrate/frame/staking/src/pallet/mod.rs
+++ b/substrate/frame/staking/src/pallet/mod.rs
@@ -25,8 +25,8 @@ use frame_election_provider_support::{
 use frame_support::{
 	pallet_prelude::*,
 	traits::{
-		Currency, Defensive, DefensiveSaturating, EnsureOrigin, EstimateNextNewSession, Get,
-		InspectLockableCurrency, LockableCurrency, OnUnbalanced, UnixTime, WithdrawReasons,
+		Defensive, DefensiveSaturating, EnsureOrigin, EstimateNextNewSession, Get,
+		InspectLockableCurrency, LockableCurrency, OnUnbalanced, UnixTime,
 	},
 	weights::Weight,
 	BoundedVec,
@@ -48,11 +48,11 @@ mod impls;
 pub use impls::*;
 
 use crate::{
-	slashing, weights::WeightInfo, AccountIdLookupOf, ActiveEraInfo, BalanceOf, DisablingStrategy,
-	EraPayout, EraRewardPoints, Exposure, ExposurePage, Forcing, LedgerIntegrityState,
-	MaxNominationsOf, NegativeImbalanceOf, Nominations, NominationsQuota, PositiveImbalanceOf,
-	RewardDestination, SessionInterface, StakingLedger, UnappliedSlash, UnlockChunk,
-	ValidatorPrefs,
+	asset, slashing, weights::WeightInfo, AccountIdLookupOf, ActiveEraInfo, BalanceOf,
+	DisablingStrategy, EraPayout, EraRewardPoints, Exposure, ExposurePage, Forcing,
+	LedgerIntegrityState, MaxNominationsOf, NegativeImbalanceOf, Nominations, NominationsQuota,
+	PositiveImbalanceOf, RewardDestination, SessionInterface, StakingLedger, UnappliedSlash,
+	UnlockChunk, ValidatorPrefs,
 };
 
 // The speculative number of spans are used as an input of the weight annotation of
@@ -779,7 +779,7 @@ pub mod pallet {
 					status
 				);
 				assert!(
-					T::Currency::free_balance(stash) >= balance,
+					asset::stakeable_balance::<T>(stash) >= balance,
 					"Stash does not have enough balance to bond."
 				);
 				frame_support::assert_ok!(<Pallet<T>>::bond(
@@ -1023,14 +1023,14 @@ pub mod pallet {
 			}
 
 			// Reject a bond which is considered to be _dust_.
-			if value < T::Currency::minimum_balance() {
+			if value < asset::existential_deposit::<T>() {
 				return Err(Error::<T>::InsufficientBond.into())
 			}
 
 			// Would fail if account has no provider.
 			frame_system::Pallet::<T>::inc_consumers(&stash)?;
 
-			let stash_balance = T::Currency::free_balance(&stash);
+			let stash_balance = asset::stakeable_balance::<T>(&stash);
 			let value = value.min(stash_balance);
 			Self::deposit_event(Event::<T>::Bonded { stash: stash.clone(), amount: value });
 			let ledger = StakingLedger::<T>::new(stash.clone(), value);
@@ -1068,7 +1068,7 @@ pub mod pallet {
 
 		/// Schedule a portion of the stash to be unlocked ready for transfer out after the bond
 		/// period ends. If this leaves an amount actively bonded less than
-		/// T::Currency::minimum_balance(), then it is increased to the full amount.
+		/// [`asset::existential_deposit`], then it is increased to the full amount.
 		///
 		/// The dispatch origin for this call must be _Signed_ by the controller, not the stash.
 		///
@@ -1124,7 +1124,7 @@ pub mod pallet {
 				ledger.active -= value;
 
 				// Avoid there being a dust balance left in the staking system.
-				if ledger.active < T::Currency::minimum_balance() {
+				if ledger.active < asset::existential_deposit::<T>() {
 					value += ledger.active;
 					ledger.active = Zero::zero();
 				}
@@ -1654,7 +1654,10 @@ pub mod pallet {
 			let initial_unlocking = ledger.unlocking.len() as u32;
 			let (ledger, rebonded_value) = ledger.rebond(value);
 			// Last check: the new active amount of ledger must be more than ED.
-			ensure!(ledger.active >= T::Currency::minimum_balance(), Error::<T>::InsufficientBond);
+			ensure!(
+				ledger.active >= asset::existential_deposit::<T>(),
+				Error::<T>::InsufficientBond
+			);
 
 			Self::deposit_event(Event::<T>::Bonded {
 				stash: ledger.stash.clone(),
@@ -1706,8 +1709,8 @@ pub mod pallet {
 			// virtual stakers should not be allowed to be reaped.
 			ensure!(!Self::is_virtual_staker(&stash), Error::<T>::VirtualStakerNotAllowed);
 
-			let ed = T::Currency::minimum_balance();
-			let origin_balance = T::Currency::total_balance(&stash);
+			let ed = asset::existential_deposit::<T>();
+			let origin_balance = asset::total_balance::<T>(&stash);
 			let ledger_total =
 				Self::ledger(Stash(stash.clone())).map(|l| l.total).unwrap_or_default();
 			let reapable = origin_balance < ed ||
@@ -2074,8 +2077,8 @@ pub mod pallet {
 			// cannot restore ledger for virtual stakers.
 			ensure!(!Self::is_virtual_staker(&stash), Error::<T>::VirtualStakerNotAllowed);
 
-			let current_lock = T::Currency::balance_locked(crate::STAKING_ID, &stash);
-			let stash_balance = T::Currency::free_balance(&stash);
+			let current_lock = asset::staked::<T>(&stash);
+			let stash_balance = asset::stakeable_balance::<T>(&stash);
 
 			let (new_controller, new_total) = match Self::inspect_bond_state(&stash) {
 				Ok(LedgerIntegrityState::Corrupted) => {
@@ -2084,12 +2087,7 @@ pub mod pallet {
 					let new_total = if let Some(total) = maybe_total {
 						let new_total = total.min(stash_balance);
 						// enforce lock == ledger.amount.
-						T::Currency::set_lock(
-							crate::STAKING_ID,
-							&stash,
-							new_total,
-							WithdrawReasons::all(),
-						);
+						asset::update_stake::<T>(&stash, new_total);
 						new_total
 					} else {
 						current_lock
@@ -2116,18 +2114,13 @@ pub mod pallet {
 					// to enforce a new ledger.total and staking lock for this stash.
 					let new_total =
 						maybe_total.ok_or(Error::<T>::CannotRestoreLedger)?.min(stash_balance);
-					T::Currency::set_lock(
-						crate::STAKING_ID,
-						&stash,
-						new_total,
-						WithdrawReasons::all(),
-					);
+					asset::update_stake::<T>(&stash, new_total);
 
 					Ok((stash.clone(), new_total))
 				},
 				Err(Error::<T>::BadState) => {
 					// the stash and ledger do not exist but lock is lingering.
-					T::Currency::remove_lock(crate::STAKING_ID, &stash);
+					asset::kill_stake::<T>(&stash);
 					ensure!(
 						Self::inspect_bond_state(&stash) == Err(Error::<T>::NotStash),
 						Error::<T>::BadState
diff --git a/substrate/frame/staking/src/slashing.rs b/substrate/frame/staking/src/slashing.rs
index 9bc8197c50b..9fb782265b8 100644
--- a/substrate/frame/staking/src/slashing.rs
+++ b/substrate/frame/staking/src/slashing.rs
@@ -50,15 +50,15 @@
 //! Based on research at <https://research.web3.foundation/en/latest/polkadot/slashing/npos.html>
 
 use crate::{
-	BalanceOf, Config, DisabledValidators, DisablingStrategy, Error, Exposure, NegativeImbalanceOf,
-	NominatorSlashInEra, Pallet, Perbill, SessionInterface, SpanSlash, UnappliedSlash,
-	ValidatorSlashInEra,
+	asset, BalanceOf, Config, DisabledValidators, DisablingStrategy, Error, Exposure,
+	NegativeImbalanceOf, NominatorSlashInEra, Pallet, Perbill, SessionInterface, SpanSlash,
+	UnappliedSlash, ValidatorSlashInEra,
 };
 use alloc::vec::Vec;
 use codec::{Decode, Encode, MaxEncodedLen};
 use frame_support::{
 	ensure,
-	traits::{Currency, Defensive, DefensiveSaturating, Imbalance, OnUnbalanced},
+	traits::{Defensive, DefensiveSaturating, Imbalance, OnUnbalanced},
 };
 use scale_info::TypeInfo;
 use sp_runtime::{
@@ -578,7 +578,7 @@ pub fn do_slash<T: Config>(
 			Err(_) => return, // nothing to do.
 		};
 
-	let value = ledger.slash(value, T::Currency::minimum_balance(), slash_era);
+	let value = ledger.slash(value, asset::existential_deposit::<T>(), slash_era);
 	if value.is_zero() {
 		// nothing to do
 		return
@@ -586,7 +586,7 @@ pub fn do_slash<T: Config>(
 
 	// Skip slashing for virtual stakers. The pallets managing them should handle the slashing.
 	if !Pallet::<T>::is_virtual_staker(stash) {
-		let (imbalance, missing) = T::Currency::slash(stash, value);
+		let (imbalance, missing) = asset::slash::<T>(stash, value);
 		slashed_imbalance.subsume(imbalance);
 
 		if !missing.is_zero() {
@@ -656,7 +656,7 @@ fn pay_reporters<T: Config>(
 
 		// this cancels out the reporter reward imbalance internally, leading
 		// to no change in total issuance.
-		T::Currency::resolve_creating(reporter, reporter_reward);
+		asset::deposit_slashed::<T>(reporter, reporter_reward);
 	}
 
 	// the rest goes to the on-slash imbalance handler (e.g. treasury)
diff --git a/substrate/frame/staking/src/testing_utils.rs b/substrate/frame/staking/src/testing_utils.rs
index 65aaa5f09de..efd4a40f1ab 100644
--- a/substrate/frame/staking/src/testing_utils.rs
+++ b/substrate/frame/staking/src/testing_utils.rs
@@ -28,7 +28,7 @@ use rand_chacha::{
 use sp_io::hashing::blake2_256;
 
 use frame_election_provider_support::SortedListProvider;
-use frame_support::{pallet_prelude::*, traits::Currency};
+use frame_support::pallet_prelude::*;
 use sp_runtime::{traits::StaticLookup, Perbill};
 
 const SEED: u32 = 0;
@@ -53,8 +53,8 @@ pub fn create_funded_user<T: Config>(
 	balance_factor: u32,
 ) -> T::AccountId {
 	let user = account(string, n, SEED);
-	let balance = T::Currency::minimum_balance() * balance_factor.into();
-	let _ = T::Currency::make_free_balance_be(&user, balance);
+	let balance = asset::existential_deposit::<T>() * balance_factor.into();
+	let _ = asset::set_stakeable_balance::<T>(&user, balance);
 	user
 }
 
@@ -65,7 +65,7 @@ pub fn create_funded_user_with_balance<T: Config>(
 	balance: BalanceOf<T>,
 ) -> T::AccountId {
 	let user = account(string, n, SEED);
-	let _ = T::Currency::make_free_balance_be(&user, balance);
+	let _ = asset::set_stakeable_balance::<T>(&user, balance);
 	user
 }
 
@@ -77,7 +77,7 @@ pub fn create_stash_controller<T: Config>(
 ) -> Result<(T::AccountId, T::AccountId), &'static str> {
 	let staker = create_funded_user::<T>("stash", n, balance_factor);
 	let amount =
-		T::Currency::minimum_balance().max(1u64.into()) * (balance_factor / 10).max(1).into();
+		asset::existential_deposit::<T>().max(1u64.into()) * (balance_factor / 10).max(1).into();
 	Staking::<T>::bond(RawOrigin::Signed(staker.clone()).into(), amount, destination)?;
 	Ok((staker.clone(), staker))
 }
@@ -96,7 +96,7 @@ pub fn create_unique_stash_controller<T: Config>(
 	} else {
 		create_funded_user::<T>("controller", n, balance_factor)
 	};
-	let amount = T::Currency::minimum_balance() * (balance_factor / 10).max(1).into();
+	let amount = asset::existential_deposit::<T>() * (balance_factor / 10).max(1).into();
 	Staking::<T>::bond(RawOrigin::Signed(stash.clone()).into(), amount, destination)?;
 
 	// update ledger to be a *different* controller to stash
@@ -129,7 +129,7 @@ pub fn create_stash_and_dead_payee<T: Config>(
 	let staker = create_funded_user::<T>("stash", n, 0);
 	// payee has no funds
 	let payee = create_funded_user::<T>("payee", n, 0);
-	let amount = T::Currency::minimum_balance() * (balance_factor / 10).max(1).into();
+	let amount = asset::existential_deposit::<T>() * (balance_factor / 10).max(1).into();
 	Staking::<T>::bond(
 		RawOrigin::Signed(staker.clone()).into(),
 		amount,
diff --git a/substrate/frame/staking/src/tests.rs b/substrate/frame/staking/src/tests.rs
index dd178a95bec..639f4096456 100644
--- a/substrate/frame/staking/src/tests.rs
+++ b/substrate/frame/staking/src/tests.rs
@@ -18,7 +18,7 @@
 //! Tests for the module.
 
 use super::{ConfigOp, Event, *};
-use crate::ledger::StakingLedgerInspect;
+use crate::{asset, ledger::StakingLedgerInspect};
 use frame_election_provider_support::{
 	bounds::{DataProviderBounds, ElectionBoundsBuilder},
 	ElectionProvider, SortedListProvider, Support,
@@ -27,7 +27,7 @@ use frame_support::{
 	assert_noop, assert_ok, assert_storage_noop,
 	dispatch::{extract_actual_weight, GetDispatchInfo, WithPostDispatchInfo},
 	pallet_prelude::*,
-	traits::{Currency, Get, InspectLockableCurrency, ReservableCurrency},
+	traits::{Currency, Get, ReservableCurrency},
 };
 
 use mock::*;
@@ -229,8 +229,8 @@ fn basic_setup_works() {
 		assert_eq!(active_era(), 0);
 
 		// Account 10 has `balance_factor` free balance
-		assert_eq!(Balances::free_balance(10), 1);
-		assert_eq!(Balances::free_balance(10), 1);
+		assert_eq!(asset::stakeable_balance::<Test>(&10), 1);
+		assert_eq!(asset::stakeable_balance::<Test>(&10), 1);
 
 		// New era is not being forced
 		assert_eq!(Staking::force_era(), Forcing::NotForcing);
@@ -311,9 +311,9 @@ fn change_controller_already_paired_once_stash() {
 #[test]
 fn rewards_should_work() {
 	ExtBuilder::default().nominate(true).session_per_era(3).build_and_execute(|| {
-		let init_balance_11 = Balances::total_balance(&11);
-		let init_balance_21 = Balances::total_balance(&21);
-		let init_balance_101 = Balances::total_balance(&101);
+		let init_balance_11 = asset::total_balance::<Test>(&11);
+		let init_balance_21 = asset::total_balance::<Test>(&21);
+		let init_balance_101 = asset::total_balance::<Test>(&101);
 
 		// Set payees
 		Payee::<Test>::insert(11, RewardDestination::Account(11));
@@ -332,9 +332,9 @@ fn rewards_should_work() {
 		start_session(1);
 		assert_eq_uvec!(Session::validators(), vec![11, 21]);
 
-		assert_eq!(Balances::total_balance(&11), init_balance_11);
-		assert_eq!(Balances::total_balance(&21), init_balance_21);
-		assert_eq!(Balances::total_balance(&101), init_balance_101);
+		assert_eq!(asset::total_balance::<Test>(&11), init_balance_11);
+		assert_eq!(asset::total_balance::<Test>(&21), init_balance_21);
+		assert_eq!(asset::total_balance::<Test>(&101), init_balance_101);
 		assert_eq!(
 			Staking::eras_reward_points(active_era()),
 			EraRewardPoints {
@@ -363,17 +363,17 @@ fn rewards_should_work() {
 		mock::make_all_reward_payment(0);
 
 		assert_eq_error_rate!(
-			Balances::total_balance(&11),
+			asset::total_balance::<Test>(&11),
 			init_balance_11 + part_for_11 * total_payout_0 * 2 / 3,
 			2,
 		);
 		assert_eq_error_rate!(
-			Balances::total_balance(&21),
+			asset::total_balance::<Test>(&21),
 			init_balance_21 + part_for_21 * total_payout_0 * 1 / 3,
 			2,
 		);
 		assert_eq_error_rate!(
-			Balances::total_balance(&101),
+			asset::total_balance::<Test>(&101),
 			init_balance_101 +
 				part_for_101_from_11 * total_payout_0 * 2 / 3 +
 				part_for_101_from_21 * total_payout_0 * 1 / 3,
@@ -402,17 +402,17 @@ fn rewards_should_work() {
 		mock::make_all_reward_payment(1);
 
 		assert_eq_error_rate!(
-			Balances::total_balance(&11),
+			asset::total_balance::<Test>(&11),
 			init_balance_11 + part_for_11 * (total_payout_0 * 2 / 3 + total_payout_1),
 			2,
 		);
 		assert_eq_error_rate!(
-			Balances::total_balance(&21),
+			asset::total_balance::<Test>(&21),
 			init_balance_21 + part_for_21 * total_payout_0 * 1 / 3,
 			2,
 		);
 		assert_eq_error_rate!(
-			Balances::total_balance(&101),
+			asset::total_balance::<Test>(&101),
 			init_balance_101 +
 				part_for_101_from_11 * (total_payout_0 * 2 / 3 + total_payout_1) +
 				part_for_101_from_21 * total_payout_0 * 1 / 3,
@@ -429,7 +429,7 @@ fn staking_should_work() {
 
 		// put some money in account that we'll use.
 		for i in 1..5 {
-			let _ = Balances::make_free_balance_be(&i, 2000);
+			let _ = asset::set_stakeable_balance::<Test>(&i, 2000);
 		}
 
 		// --- Block 2:
@@ -611,7 +611,7 @@ fn nominating_and_rewards_should_work() {
 			// give the man some money
 			let initial_balance = 1000;
 			for i in [1, 3, 5, 11, 21].iter() {
-				let _ = Balances::make_free_balance_be(i, initial_balance);
+				let _ = asset::set_stakeable_balance::<Test>(&i, initial_balance);
 			}
 
 			// bond two account pairs and state interest in nomination.
@@ -636,12 +636,12 @@ fn nominating_and_rewards_should_work() {
 			assert_eq_uvec!(validator_controllers(), vec![21, 11]);
 
 			// old validators must have already received some rewards.
-			let initial_balance_41 = Balances::total_balance(&41);
-			let mut initial_balance_21 = Balances::total_balance(&21);
+			let initial_balance_41 = asset::total_balance::<Test>(&41);
+			let mut initial_balance_21 = asset::total_balance::<Test>(&21);
 			mock::make_all_reward_payment(0);
-			assert_eq!(Balances::total_balance(&41), initial_balance_41 + total_payout_0 / 2);
-			assert_eq!(Balances::total_balance(&21), initial_balance_21 + total_payout_0 / 2);
-			initial_balance_21 = Balances::total_balance(&21);
+			assert_eq!(asset::total_balance::<Test>(&41), initial_balance_41 + total_payout_0 / 2);
+			assert_eq!(asset::total_balance::<Test>(&21), initial_balance_21 + total_payout_0 / 2);
+			initial_balance_21 = asset::total_balance::<Test>(&21);
 
 			assert_eq!(ErasStakersPaged::<Test>::iter_prefix_values((active_era(),)).count(), 2);
 			assert_eq!(
@@ -683,30 +683,30 @@ fn nominating_and_rewards_should_work() {
 			// Nominator 2: has [400/1800 ~ 2/9 from 10] + [600/2200 ~ 3/11 from 21]'s reward. ==>
 			// 2/9 + 3/11
 			assert_eq_error_rate!(
-				Balances::total_balance(&1),
+				asset::total_balance::<Test>(&1),
 				initial_balance + (2 * payout_for_11 / 9 + 3 * payout_for_21 / 11),
 				2,
 			);
 			// Nominator 3: has [400/1800 ~ 2/9 from 10] + [600/2200 ~ 3/11 from 21]'s reward. ==>
 			// 2/9 + 3/11
-			assert_eq!(Balances::total_balance(&3), initial_balance);
+			assert_eq!(asset::total_balance::<Test>(&3), initial_balance);
 			// 333 is the reward destination for 3.
 			assert_eq_error_rate!(
-				Balances::total_balance(&333),
+				asset::total_balance::<Test>(&333),
 				2 * payout_for_11 / 9 + 3 * payout_for_21 / 11,
 				2
 			);
 
 			// Validator 11: got 800 / 1800 external stake => 8/18 =? 4/9 => Validator's share = 5/9
 			assert_eq_error_rate!(
-				Balances::total_balance(&11),
+				asset::total_balance::<Test>(&11),
 				initial_balance + 5 * payout_for_11 / 9,
 				2,
 			);
 			// Validator 21: got 1200 / 2200 external stake => 12/22 =? 6/11 => Validator's share =
 			// 5/11
 			assert_eq_error_rate!(
-				Balances::total_balance(&21),
+				asset::total_balance::<Test>(&21),
 				initial_balance_21 + 5 * payout_for_21 / 11,
 				2,
 			);
@@ -993,7 +993,7 @@ fn cannot_transfer_staked_balance() {
 		// Confirm account 11 is stashed
 		assert_eq!(Staking::bonded(&11), Some(11));
 		// Confirm account 11 has some free balance
-		assert_eq!(Balances::free_balance(11), 1000);
+		assert_eq!(asset::stakeable_balance::<Test>(&11), 1000);
 		// Confirm account 11 (via controller) is totally staked
 		assert_eq!(Staking::eras_stakers(active_era(), &11).total, 1000);
 		// Confirm account 11 cannot transfer as a result
@@ -1003,7 +1003,7 @@ fn cannot_transfer_staked_balance() {
 		);
 
 		// Give account 11 extra free balance
-		let _ = Balances::make_free_balance_be(&11, 10000);
+		let _ = asset::set_stakeable_balance::<Test>(&11, 10000);
 		// Confirm that account 11 can now transfer some balance
 		assert_ok!(Balances::transfer_allow_death(RuntimeOrigin::signed(11), 21, 1));
 	});
@@ -1018,7 +1018,7 @@ fn cannot_transfer_staked_balance_2() {
 		// Confirm account 21 is stashed
 		assert_eq!(Staking::bonded(&21), Some(21));
 		// Confirm account 21 has some free balance
-		assert_eq!(Balances::free_balance(21), 2000);
+		assert_eq!(asset::stakeable_balance::<Test>(&21), 2000);
 		// Confirm account 21 (via controller) is totally staked
 		assert_eq!(Staking::eras_stakers(active_era(), &21).total, 1000);
 		// Confirm account 21 can transfer at most 1000
@@ -1037,14 +1037,14 @@ fn cannot_reserve_staked_balance() {
 		// Confirm account 11 is stashed
 		assert_eq!(Staking::bonded(&11), Some(11));
 		// Confirm account 11 has some free balance
-		assert_eq!(Balances::free_balance(11), 1000);
+		assert_eq!(asset::stakeable_balance::<Test>(&11), 1000);
 		// Confirm account 11 (via controller 10) is totally staked
 		assert_eq!(Staking::eras_stakers(active_era(), &11).own, 1000);
 		// Confirm account 11 cannot reserve as a result
 		assert_noop!(Balances::reserve(&11, 1), BalancesError::<Test, _>::LiquidityRestrictions);
 
 		// Give account 11 extra free balance
-		let _ = Balances::make_free_balance_be(&11, 10000);
+		let _ = asset::set_stakeable_balance::<Test>(&11, 10000);
 		// Confirm account 11 can now reserve balance
 		assert_ok!(Balances::reserve(&11, 1));
 	});
@@ -1057,9 +1057,9 @@ fn reward_destination_works() {
 		// Check that account 11 is a validator
 		assert!(Session::validators().contains(&11));
 		// Check the balance of the validator account
-		assert_eq!(Balances::free_balance(10), 1);
+		assert_eq!(asset::stakeable_balance::<Test>(&10), 1);
 		// Check the balance of the stash account
-		assert_eq!(Balances::free_balance(11), 1000);
+		assert_eq!(asset::stakeable_balance::<Test>(&11), 1000);
 		// Check how much is at stake
 		assert_eq!(
 			Staking::ledger(11.into()).unwrap(),
@@ -1082,7 +1082,7 @@ fn reward_destination_works() {
 		// Check that RewardDestination is Staked
 		assert_eq!(Staking::payee(11.into()), Some(RewardDestination::Staked));
 		// Check that reward went to the stash account of validator
-		assert_eq!(Balances::free_balance(11), 1000 + total_payout_0);
+		assert_eq!(asset::stakeable_balance::<Test>(&11), 1000 + total_payout_0);
 		// Check that amount at stake increased accordingly
 		assert_eq!(
 			Staking::ledger(11.into()).unwrap(),
@@ -1111,7 +1111,7 @@ fn reward_destination_works() {
 		// Check that RewardDestination is Stash
 		assert_eq!(Staking::payee(11.into()), Some(RewardDestination::Stash));
 		// Check that reward went to the stash account
-		assert_eq!(Balances::free_balance(11), 1000 + total_payout_0 + total_payout_1);
+		assert_eq!(asset::stakeable_balance::<Test>(&11), 1000 + total_payout_0 + total_payout_1);
 		// Record this value
 		let recorded_stash_balance = 1000 + total_payout_0 + total_payout_1;
 		// Check that amount at stake is NOT increased
@@ -1133,7 +1133,7 @@ fn reward_destination_works() {
 		<Payee<Test>>::insert(&11, RewardDestination::Account(11));
 
 		// Check controller balance
-		assert_eq!(Balances::free_balance(11), 23150);
+		assert_eq!(asset::stakeable_balance::<Test>(&11), 23150);
 
 		// Compute total payout now for whole duration as other parameter won't change
 		let total_payout_2 = current_total_payout_for_duration(reward_time_per_era());
@@ -1145,7 +1145,7 @@ fn reward_destination_works() {
 		// Check that RewardDestination is Account(11)
 		assert_eq!(Staking::payee(11.into()), Some(RewardDestination::Account(11)));
 		// Check that reward went to the controller account
-		assert_eq!(Balances::free_balance(11), recorded_stash_balance + total_payout_2);
+		assert_eq!(asset::stakeable_balance::<Test>(&11), recorded_stash_balance + total_payout_2);
 		// Check that amount at stake is NOT increased
 		assert_eq!(
 			Staking::ledger(11.into()).unwrap(),
@@ -1179,8 +1179,8 @@ fn validator_payment_prefs_work() {
 		mock::start_active_era(1);
 		mock::make_all_reward_payment(0);
 
-		let balance_era_1_11 = Balances::total_balance(&11);
-		let balance_era_1_101 = Balances::total_balance(&101);
+		let balance_era_1_11 = asset::total_balance::<Test>(&11);
+		let balance_era_1_101 = asset::total_balance::<Test>(&101);
 
 		// Compute total payout now for whole duration as other parameter won't change
 		let total_payout_1 = current_total_payout_for_duration(reward_time_per_era());
@@ -1194,8 +1194,16 @@ fn validator_payment_prefs_work() {
 		let shared_cut = total_payout_1 - taken_cut;
 		let reward_of_10 = shared_cut * exposure_1.own / exposure_1.total + taken_cut;
 		let reward_of_100 = shared_cut * exposure_1.others[0].value / exposure_1.total;
-		assert_eq_error_rate!(Balances::total_balance(&11), balance_era_1_11 + reward_of_10, 2);
-		assert_eq_error_rate!(Balances::total_balance(&101), balance_era_1_101 + reward_of_100, 2);
+		assert_eq_error_rate!(
+			asset::total_balance::<Test>(&11),
+			balance_era_1_11 + reward_of_10,
+			2
+		);
+		assert_eq_error_rate!(
+			asset::total_balance::<Test>(&101),
+			balance_era_1_101 + reward_of_100,
+			2
+		);
 	});
 }
 
@@ -1222,7 +1230,7 @@ fn bond_extra_works() {
 		);
 
 		// Give account 11 some large free balance greater than total
-		let _ = Balances::make_free_balance_be(&11, 1000000);
+		let _ = asset::set_stakeable_balance::<Test>(&11, 1000000);
 
 		// Call the bond_extra function from controller, add only 100
 		assert_ok!(Staking::bond_extra(RuntimeOrigin::signed(11), 100));
@@ -1284,13 +1292,13 @@ fn bond_extra_and_withdraw_unbonded_works() {
 		assert_ok!(Staking::set_payee(RuntimeOrigin::signed(11), RewardDestination::Stash));
 
 		// Give account 11 some large free balance greater than total
-		let _ = Balances::make_free_balance_be(&11, 1000000);
+		let _ = asset::set_stakeable_balance::<Test>(&11, 1000000);
 
 		// Initial config should be correct
 		assert_eq!(active_era(), 0);
 
 		// check the balance of a validator accounts.
-		assert_eq!(Balances::total_balance(&11), 1000000);
+		assert_eq!(asset::total_balance::<Test>(&11), 1000000);
 
 		// confirm that 10 is a normal validator and gets paid at the end of the era.
 		mock::start_active_era(1);
@@ -1495,7 +1503,7 @@ fn rebond_works() {
 		assert_ok!(Staking::set_payee(RuntimeOrigin::signed(11), RewardDestination::Stash));
 
 		// Give account 11 some large free balance greater than total
-		let _ = Balances::make_free_balance_be(&11, 1000000);
+		let _ = asset::set_stakeable_balance::<Test>(&11, 1000000);
 
 		// confirm that 10 is a normal validator and gets paid at the end of the era.
 		mock::start_active_era(1);
@@ -1621,7 +1629,7 @@ fn rebond_is_fifo() {
 		assert_ok!(Staking::set_payee(RuntimeOrigin::signed(11), RewardDestination::Stash));
 
 		// Give account 11 some large free balance greater than total
-		let _ = Balances::make_free_balance_be(&11, 1000000);
+		let _ = asset::set_stakeable_balance::<Test>(&11, 1000000);
 
 		// confirm that 10 is a normal validator and gets paid at the end of the era.
 		mock::start_active_era(1);
@@ -1717,7 +1725,7 @@ fn rebond_emits_right_value_in_event() {
 		assert_ok!(Staking::set_payee(RuntimeOrigin::signed(11), RewardDestination::Stash));
 
 		// Give account 11 some large free balance greater than total
-		let _ = Balances::make_free_balance_be(&11, 1000000);
+		let _ = asset::set_stakeable_balance::<Test>(&11, 1000000);
 
 		// confirm that 10 is a normal validator and gets paid at the end of the era.
 		mock::start_active_era(1);
@@ -1852,8 +1860,8 @@ fn reward_to_stake_works() {
 			assert_eq!(Staking::eras_stakers(active_era(), &21).total, 2000);
 
 			// Give the man some money.
-			let _ = Balances::make_free_balance_be(&10, 1000);
-			let _ = Balances::make_free_balance_be(&20, 1000);
+			let _ = asset::set_stakeable_balance::<Test>(&10, 1000);
+			let _ = asset::set_stakeable_balance::<Test>(&20, 1000);
 
 			// Bypass logic and change current exposure
 			EraInfo::<Test>::set_exposure(0, &21, Exposure { total: 69, own: 69, others: vec![] });
@@ -1880,7 +1888,7 @@ fn reward_to_stake_works() {
 			assert_eq!(Staking::eras_stakers(active_era(), &11).total, 1000);
 			assert_eq!(Staking::eras_stakers(active_era(), &21).total, 2000);
 
-			let _11_balance = Balances::free_balance(&11);
+			let _11_balance = asset::stakeable_balance::<Test>(&11);
 			assert_eq!(_11_balance, 1000 + total_payout_0 / 2);
 
 			// Trigger another new era as the info are frozen before the era start.
@@ -1899,7 +1907,7 @@ fn reap_stash_works() {
 		.balance_factor(10)
 		.build_and_execute(|| {
 			// given
-			assert_eq!(Balances::balance_locked(STAKING_ID, &11), 10 * 1000);
+			assert_eq!(asset::staked::<Test>(&11), 10 * 1000);
 			assert_eq!(Staking::bonded(&11), Some(11));
 
 			assert!(<Ledger<Test>>::contains_key(&11));
@@ -1926,7 +1934,7 @@ fn reap_stash_works() {
 			assert!(!<Validators<Test>>::contains_key(&11));
 			assert!(!<Payee<Test>>::contains_key(&11));
 			// lock is removed.
-			assert_eq!(Balances::balance_locked(STAKING_ID, &11), 0);
+			assert_eq!(asset::staked::<Test>(&11), 0);
 		});
 }
 
@@ -1937,7 +1945,7 @@ fn reap_stash_works_with_existential_deposit_zero() {
 		.balance_factor(10)
 		.build_and_execute(|| {
 			// given
-			assert_eq!(Balances::balance_locked(STAKING_ID, &11), 10 * 1000);
+			assert_eq!(asset::staked::<Test>(&11), 10 * 1000);
 			assert_eq!(Staking::bonded(&11), Some(11));
 
 			assert!(<Ledger<Test>>::contains_key(&11));
@@ -1964,7 +1972,7 @@ fn reap_stash_works_with_existential_deposit_zero() {
 			assert!(!<Validators<Test>>::contains_key(&11));
 			assert!(!<Payee<Test>>::contains_key(&11));
 			// lock is removed.
-			assert_eq!(Balances::balance_locked(STAKING_ID, &11), 0);
+			assert_eq!(asset::staked::<Test>(&11), 0);
 		});
 }
 
@@ -2111,8 +2119,8 @@ fn bond_with_little_staked_value_bounded() {
 			// setup
 			assert_ok!(Staking::chill(RuntimeOrigin::signed(31)));
 			assert_ok!(Staking::set_payee(RuntimeOrigin::signed(11), RewardDestination::Stash));
-			let init_balance_1 = Balances::free_balance(&1);
-			let init_balance_11 = Balances::free_balance(&11);
+			let init_balance_1 = asset::stakeable_balance::<Test>(&1);
+			let init_balance_11 = asset::stakeable_balance::<Test>(&11);
 
 			// Stingy validator.
 			assert_ok!(Staking::bond(RuntimeOrigin::signed(1), 1, RewardDestination::Account(1)));
@@ -2137,12 +2145,12 @@ fn bond_with_little_staked_value_bounded() {
 
 			// Old ones are rewarded.
 			assert_eq_error_rate!(
-				Balances::free_balance(11),
+				asset::stakeable_balance::<Test>(&11),
 				init_balance_11 + total_payout_0 / 3,
 				1
 			);
 			// no rewards paid to 2. This was initial election.
-			assert_eq!(Balances::free_balance(1), init_balance_1);
+			assert_eq!(asset::stakeable_balance::<Test>(&1), init_balance_1);
 
 			// reward era 2
 			let total_payout_1 = current_total_payout_for_duration(reward_time_per_era());
@@ -2155,12 +2163,12 @@ fn bond_with_little_staked_value_bounded() {
 
 			// 2 is now rewarded.
 			assert_eq_error_rate!(
-				Balances::free_balance(1),
+				asset::stakeable_balance::<Test>(&1),
 				init_balance_1 + total_payout_1 / 3,
 				1
 			);
 			assert_eq_error_rate!(
-				Balances::free_balance(&11),
+				asset::stakeable_balance::<Test>(&11),
 				init_balance_11 + total_payout_0 / 3 + total_payout_1 / 3,
 				2,
 			);
@@ -2188,7 +2196,7 @@ fn bond_with_duplicate_vote_should_be_ignored_by_election_provider() {
 			// give the man some money.
 			let initial_balance = 1000;
 			for i in [1, 2, 3, 4].iter() {
-				let _ = Balances::make_free_balance_be(i, initial_balance);
+				let _ = asset::set_stakeable_balance::<Test>(&i, initial_balance);
 			}
 
 			assert_ok!(Staking::bond(
@@ -2241,7 +2249,7 @@ fn bond_with_duplicate_vote_should_be_ignored_by_election_provider_elected() {
 			// give the man some money.
 			let initial_balance = 1000;
 			for i in [1, 2, 3, 4].iter() {
-				let _ = Balances::make_free_balance_be(i, initial_balance);
+				let _ = asset::set_stakeable_balance::<Test>(&i, initial_balance);
 			}
 
 			assert_ok!(Staking::bond(
@@ -2317,7 +2325,7 @@ fn reward_validator_slashing_validator_does_not_overflow() {
 		assert!(stake.checked_mul(reward_slash).is_none());
 
 		// Set staker
-		let _ = Balances::make_free_balance_be(&11, stake);
+		let _ = asset::set_stakeable_balance::<Test>(&11, stake);
 
 		let exposure = Exposure::<AccountId, Balance> { total: stake, own: stake, others: vec![] };
 		let reward = EraRewardPoints::<AccountId> {
@@ -2330,11 +2338,11 @@ fn reward_validator_slashing_validator_does_not_overflow() {
 		EraInfo::<Test>::set_exposure(0, &11, exposure);
 		ErasValidatorReward::<Test>::insert(0, stake);
 		assert_ok!(Staking::payout_stakers_by_page(RuntimeOrigin::signed(1337), 11, 0, 0));
-		assert_eq!(Balances::total_balance(&11), stake * 2);
+		assert_eq!(asset::total_balance::<Test>(&11), stake * 2);
 
 		// Set staker
-		let _ = Balances::make_free_balance_be(&11, stake);
-		let _ = Balances::make_free_balance_be(&2, stake);
+		let _ = asset::set_stakeable_balance::<Test>(&11, stake);
+		let _ = asset::set_stakeable_balance::<Test>(&2, stake);
 
 		// only slashes out of bonded stake are applied. without this line, it is 0.
 		Staking::bond(RuntimeOrigin::signed(2), stake - 1, RewardDestination::Staked).unwrap();
@@ -2358,8 +2366,8 @@ fn reward_validator_slashing_validator_does_not_overflow() {
 			&[Perbill::from_percent(100)],
 		);
 
-		assert_eq!(Balances::total_balance(&11), stake - 1);
-		assert_eq!(Balances::total_balance(&2), 1);
+		assert_eq!(asset::total_balance::<Test>(&11), stake - 1);
+		assert_eq!(asset::total_balance::<Test>(&2), 1);
 	})
 }
 
@@ -2526,7 +2534,7 @@ fn slashing_performed_according_exposure() {
 		);
 
 		// The stash account should be slashed for 250 (50% of 500).
-		assert_eq!(Balances::free_balance(11), 1000 - 250);
+		assert_eq!(asset::stakeable_balance::<Test>(&11), 1000 - 250);
 	});
 }
 
@@ -2619,8 +2627,8 @@ fn reporters_receive_their_slice() {
 		// 50% * (10% * initial_balance / 2)
 		let reward = (initial_balance / 20) / 2;
 		let reward_each = reward / 2; // split into two pieces.
-		assert_eq!(Balances::free_balance(1), 10 + reward_each);
-		assert_eq!(Balances::free_balance(2), 20 + reward_each);
+		assert_eq!(asset::stakeable_balance::<Test>(&1), 10 + reward_each);
+		assert_eq!(asset::stakeable_balance::<Test>(&2), 20 + reward_each);
 	});
 }
 
@@ -2645,7 +2653,7 @@ fn subsequent_reports_in_same_span_pay_out_less() {
 		// F1 * (reward_proportion * slash - 0)
 		// 50% * (10% * initial_balance * 20%)
 		let reward = (initial_balance / 5) / 20;
-		assert_eq!(Balances::free_balance(1), 10 + reward);
+		assert_eq!(asset::stakeable_balance::<Test>(&1), 10 + reward);
 
 		on_offence_now(
 			&[OffenceDetails {
@@ -2660,7 +2668,7 @@ fn subsequent_reports_in_same_span_pay_out_less() {
 		// F1 * (reward_proportion * slash - prior_payout)
 		// 50% * (10% * (initial_balance / 2) - prior_payout)
 		let reward = ((initial_balance / 20) - prior_payout) / 2;
-		assert_eq!(Balances::free_balance(1), 10 + prior_payout + reward);
+		assert_eq!(asset::stakeable_balance::<Test>(&1), 10 + prior_payout + reward);
 	});
 }
 
@@ -2668,14 +2676,17 @@ fn subsequent_reports_in_same_span_pay_out_less() {
 fn invulnerables_are_not_slashed() {
 	// For invulnerable validators no slashing is performed.
 	ExtBuilder::default().invulnerables(vec![11]).build_and_execute(|| {
-		assert_eq!(Balances::free_balance(11), 1000);
-		assert_eq!(Balances::free_balance(21), 2000);
+		assert_eq!(asset::stakeable_balance::<Test>(&11), 1000);
+		assert_eq!(asset::stakeable_balance::<Test>(&21), 2000);
 
 		let exposure = Staking::eras_stakers(active_era(), &21);
 		let initial_balance = Staking::slashable_balance_of(&21);
 
-		let nominator_balances: Vec<_> =
-			exposure.others.iter().map(|o| Balances::free_balance(&o.who)).collect();
+		let nominator_balances: Vec<_> = exposure
+			.others
+			.iter()
+			.map(|o| asset::stakeable_balance::<Test>(&o.who))
+			.collect();
 
 		on_offence_now(
 			&[
@@ -2692,14 +2703,14 @@ fn invulnerables_are_not_slashed() {
 		);
 
 		// The validator 11 hasn't been slashed, but 21 has been.
-		assert_eq!(Balances::free_balance(11), 1000);
+		assert_eq!(asset::stakeable_balance::<Test>(&11), 1000);
 		// 2000 - (0.2 * initial_balance)
-		assert_eq!(Balances::free_balance(21), 2000 - (2 * initial_balance / 10));
+		assert_eq!(asset::stakeable_balance::<Test>(&21), 2000 - (2 * initial_balance / 10));
 
 		// ensure that nominators were slashed as well.
 		for (initial_balance, other) in nominator_balances.into_iter().zip(exposure.others) {
 			assert_eq!(
-				Balances::free_balance(&other.who),
+				asset::stakeable_balance::<Test>(&other.who),
 				initial_balance - (2 * other.value / 10),
 			);
 		}
@@ -2710,7 +2721,7 @@ fn invulnerables_are_not_slashed() {
 fn dont_slash_if_fraction_is_zero() {
 	// Don't slash if the fraction is zero.
 	ExtBuilder::default().build_and_execute(|| {
-		assert_eq!(Balances::free_balance(11), 1000);
+		assert_eq!(asset::stakeable_balance::<Test>(&11), 1000);
 
 		on_offence_now(
 			&[OffenceDetails {
@@ -2721,7 +2732,7 @@ fn dont_slash_if_fraction_is_zero() {
 		);
 
 		// The validator hasn't been slashed. The new era is not forced.
-		assert_eq!(Balances::free_balance(11), 1000);
+		assert_eq!(asset::stakeable_balance::<Test>(&11), 1000);
 		assert_eq!(Staking::force_era(), Forcing::NotForcing);
 	});
 }
@@ -2731,7 +2742,7 @@ fn only_slash_for_max_in_era() {
 	// multiple slashes within one era are only applied if it is more than any previous slash in the
 	// same era.
 	ExtBuilder::default().build_and_execute(|| {
-		assert_eq!(Balances::free_balance(11), 1000);
+		assert_eq!(asset::stakeable_balance::<Test>(&11), 1000);
 
 		on_offence_now(
 			&[OffenceDetails {
@@ -2742,7 +2753,7 @@ fn only_slash_for_max_in_era() {
 		);
 
 		// The validator has been slashed and has been force-chilled.
-		assert_eq!(Balances::free_balance(11), 500);
+		assert_eq!(asset::stakeable_balance::<Test>(&11), 500);
 		assert_eq!(Staking::force_era(), Forcing::NotForcing);
 
 		on_offence_now(
@@ -2754,7 +2765,7 @@ fn only_slash_for_max_in_era() {
 		);
 
 		// The validator has not been slashed additionally.
-		assert_eq!(Balances::free_balance(11), 500);
+		assert_eq!(asset::stakeable_balance::<Test>(&11), 500);
 
 		on_offence_now(
 			&[OffenceDetails {
@@ -2765,7 +2776,7 @@ fn only_slash_for_max_in_era() {
 		);
 
 		// The validator got slashed 10% more.
-		assert_eq!(Balances::free_balance(11), 400);
+		assert_eq!(asset::stakeable_balance::<Test>(&11), 400);
 	})
 }
 
@@ -2776,7 +2787,7 @@ fn garbage_collection_after_slashing() {
 		.existential_deposit(2)
 		.balance_factor(2)
 		.build_and_execute(|| {
-			assert_eq!(Balances::free_balance(11), 2000);
+			assert_eq!(asset::stakeable_balance::<Test>(&11), 2000);
 
 			on_offence_now(
 				&[OffenceDetails {
@@ -2786,7 +2797,7 @@ fn garbage_collection_after_slashing() {
 				&[Perbill::from_percent(10)],
 			);
 
-			assert_eq!(Balances::free_balance(11), 2000 - 200);
+			assert_eq!(asset::stakeable_balance::<Test>(&11), 2000 - 200);
 			assert!(SlashingSpans::<Test>::get(&11).is_some());
 			assert_eq!(SpanSlash::<Test>::get(&(11, 0)).amount(), &200);
 
@@ -2801,8 +2812,8 @@ fn garbage_collection_after_slashing() {
 			// validator and nominator slash in era are garbage-collected by era change,
 			// so we don't test those here.
 
-			assert_eq!(Balances::free_balance(11), 2);
-			assert_eq!(Balances::total_balance(&11), 2);
+			assert_eq!(asset::stakeable_balance::<Test>(&11), 2);
+			assert_eq!(asset::total_balance::<Test>(&11), 2);
 
 			let slashing_spans = SlashingSpans::<Test>::get(&11).unwrap();
 			assert_eq!(slashing_spans.iter().count(), 2);
@@ -2826,11 +2837,11 @@ fn garbage_collection_on_window_pruning() {
 	ExtBuilder::default().build_and_execute(|| {
 		mock::start_active_era(1);
 
-		assert_eq!(Balances::free_balance(11), 1000);
+		assert_eq!(asset::stakeable_balance::<Test>(&11), 1000);
 		let now = active_era();
 
 		let exposure = Staking::eras_stakers(now, &11);
-		assert_eq!(Balances::free_balance(101), 2000);
+		assert_eq!(asset::stakeable_balance::<Test>(&101), 2000);
 		let nominated_value = exposure.others.iter().find(|o| o.who == 101).unwrap().value;
 
 		on_offence_now(
@@ -2841,8 +2852,8 @@ fn garbage_collection_on_window_pruning() {
 			&[Perbill::from_percent(10)],
 		);
 
-		assert_eq!(Balances::free_balance(11), 900);
-		assert_eq!(Balances::free_balance(101), 2000 - (nominated_value / 10));
+		assert_eq!(asset::stakeable_balance::<Test>(&11), 900);
+		assert_eq!(asset::stakeable_balance::<Test>(&101), 2000 - (nominated_value / 10));
 
 		assert!(ValidatorSlashInEra::<Test>::get(&now, &11).is_some());
 		assert!(NominatorSlashInEra::<Test>::get(&now, &101).is_some());
@@ -2867,9 +2878,9 @@ fn slashing_nominators_by_span_max() {
 		mock::start_active_era(2);
 		mock::start_active_era(3);
 
-		assert_eq!(Balances::free_balance(11), 1000);
-		assert_eq!(Balances::free_balance(21), 2000);
-		assert_eq!(Balances::free_balance(101), 2000);
+		assert_eq!(asset::stakeable_balance::<Test>(&11), 1000);
+		assert_eq!(asset::stakeable_balance::<Test>(&21), 2000);
+		assert_eq!(asset::stakeable_balance::<Test>(&101), 2000);
 		assert_eq!(Staking::slashable_balance_of(&21), 1000);
 
 		let exposure_11 = Staking::eras_stakers(active_era(), &11);
@@ -2886,10 +2897,10 @@ fn slashing_nominators_by_span_max() {
 			2,
 		);
 
-		assert_eq!(Balances::free_balance(11), 900);
+		assert_eq!(asset::stakeable_balance::<Test>(&11), 900);
 
 		let slash_1_amount = Perbill::from_percent(10) * nominated_value_11;
-		assert_eq!(Balances::free_balance(101), 2000 - slash_1_amount);
+		assert_eq!(asset::stakeable_balance::<Test>(&101), 2000 - slash_1_amount);
 
 		let expected_spans = vec![
 			slashing::SlashingSpan { index: 1, start: 4, length: None },
@@ -2913,14 +2924,14 @@ fn slashing_nominators_by_span_max() {
 		);
 
 		// 11 was not further slashed, but 21 and 101 were.
-		assert_eq!(Balances::free_balance(11), 900);
-		assert_eq!(Balances::free_balance(21), 1700);
+		assert_eq!(asset::stakeable_balance::<Test>(&11), 900);
+		assert_eq!(asset::stakeable_balance::<Test>(&21), 1700);
 
 		let slash_2_amount = Perbill::from_percent(30) * nominated_value_21;
 		assert!(slash_2_amount > slash_1_amount);
 
 		// only the maximum slash in a single span is taken.
-		assert_eq!(Balances::free_balance(101), 2000 - slash_2_amount);
+		assert_eq!(asset::stakeable_balance::<Test>(&101), 2000 - slash_2_amount);
 
 		// third slash: in same era and on same validator as first, higher
 		// in-era value, but lower slash value than slash 2.
@@ -2934,15 +2945,15 @@ fn slashing_nominators_by_span_max() {
 		);
 
 		// 11 was further slashed, but 21 and 101 were not.
-		assert_eq!(Balances::free_balance(11), 800);
-		assert_eq!(Balances::free_balance(21), 1700);
+		assert_eq!(asset::stakeable_balance::<Test>(&11), 800);
+		assert_eq!(asset::stakeable_balance::<Test>(&21), 1700);
 
 		let slash_3_amount = Perbill::from_percent(20) * nominated_value_21;
 		assert!(slash_3_amount < slash_2_amount);
 		assert!(slash_3_amount > slash_1_amount);
 
 		// only the maximum slash in a single span is taken.
-		assert_eq!(Balances::free_balance(101), 2000 - slash_2_amount);
+		assert_eq!(asset::stakeable_balance::<Test>(&101), 2000 - slash_2_amount);
 	});
 }
 
@@ -2953,7 +2964,7 @@ fn slashes_are_summed_across_spans() {
 		mock::start_active_era(2);
 		mock::start_active_era(3);
 
-		assert_eq!(Balances::free_balance(21), 2000);
+		assert_eq!(asset::stakeable_balance::<Test>(&21), 2000);
 		assert_eq!(Staking::slashable_balance_of(&21), 1000);
 
 		let get_span = |account| SlashingSpans::<Test>::get(&account).unwrap();
@@ -2972,7 +2983,7 @@ fn slashes_are_summed_across_spans() {
 		];
 
 		assert_eq!(get_span(21).iter().collect::<Vec<_>>(), expected_spans);
-		assert_eq!(Balances::free_balance(21), 1900);
+		assert_eq!(asset::stakeable_balance::<Test>(&21), 1900);
 
 		// 21 has been force-chilled. re-signal intent to validate.
 		Staking::validate(RuntimeOrigin::signed(21), Default::default()).unwrap();
@@ -2996,7 +3007,7 @@ fn slashes_are_summed_across_spans() {
 		];
 
 		assert_eq!(get_span(21).iter().collect::<Vec<_>>(), expected_spans);
-		assert_eq!(Balances::free_balance(21), 1810);
+		assert_eq!(asset::stakeable_balance::<Test>(&21), 1810);
 	});
 }
 
@@ -3005,10 +3016,10 @@ fn deferred_slashes_are_deferred() {
 	ExtBuilder::default().slash_defer_duration(2).build_and_execute(|| {
 		mock::start_active_era(1);
 
-		assert_eq!(Balances::free_balance(11), 1000);
+		assert_eq!(asset::stakeable_balance::<Test>(&11), 1000);
 
 		let exposure = Staking::eras_stakers(active_era(), &11);
-		assert_eq!(Balances::free_balance(101), 2000);
+		assert_eq!(asset::stakeable_balance::<Test>(&101), 2000);
 		let nominated_value = exposure.others.iter().find(|o| o.who == 101).unwrap().value;
 
 		System::reset_events();
@@ -3024,25 +3035,25 @@ fn deferred_slashes_are_deferred() {
 		// nominations are not removed regardless of the deferring.
 		assert_eq!(Staking::nominators(101).unwrap().targets, vec![11, 21]);
 
-		assert_eq!(Balances::free_balance(11), 1000);
-		assert_eq!(Balances::free_balance(101), 2000);
+		assert_eq!(asset::stakeable_balance::<Test>(&11), 1000);
+		assert_eq!(asset::stakeable_balance::<Test>(&101), 2000);
 
 		mock::start_active_era(2);
 
-		assert_eq!(Balances::free_balance(11), 1000);
-		assert_eq!(Balances::free_balance(101), 2000);
+		assert_eq!(asset::stakeable_balance::<Test>(&11), 1000);
+		assert_eq!(asset::stakeable_balance::<Test>(&101), 2000);
 
 		mock::start_active_era(3);
 
-		assert_eq!(Balances::free_balance(11), 1000);
-		assert_eq!(Balances::free_balance(101), 2000);
+		assert_eq!(asset::stakeable_balance::<Test>(&11), 1000);
+		assert_eq!(asset::stakeable_balance::<Test>(&101), 2000);
 
 		// at the start of era 4, slashes from era 1 are processed,
 		// after being deferred for at least 2 full eras.
 		mock::start_active_era(4);
 
-		assert_eq!(Balances::free_balance(11), 900);
-		assert_eq!(Balances::free_balance(101), 2000 - (nominated_value / 10));
+		assert_eq!(asset::stakeable_balance::<Test>(&11), 900);
+		assert_eq!(asset::stakeable_balance::<Test>(&101), 2000 - (nominated_value / 10));
 
 		assert!(matches!(
 			staking_events_since_last_call().as_slice(),
@@ -3140,8 +3151,8 @@ fn staker_cannot_bail_deferred_slash() {
 	ExtBuilder::default().slash_defer_duration(2).build_and_execute(|| {
 		mock::start_active_era(1);
 
-		assert_eq!(Balances::free_balance(11), 1000);
-		assert_eq!(Balances::free_balance(101), 2000);
+		assert_eq!(asset::stakeable_balance::<Test>(&11), 1000);
+		assert_eq!(asset::stakeable_balance::<Test>(&101), 2000);
 
 		let exposure = Staking::eras_stakers(active_era(), &11);
 		let nominated_value = exposure.others.iter().find(|o| o.who == 101).unwrap().value;
@@ -3173,20 +3184,20 @@ fn staker_cannot_bail_deferred_slash() {
 		);
 
 		// no slash yet.
-		assert_eq!(Balances::free_balance(11), 1000);
-		assert_eq!(Balances::free_balance(101), 2000);
+		assert_eq!(asset::stakeable_balance::<Test>(&11), 1000);
+		assert_eq!(asset::stakeable_balance::<Test>(&101), 2000);
 
 		// no slash yet.
 		mock::start_active_era(2);
-		assert_eq!(Balances::free_balance(11), 1000);
-		assert_eq!(Balances::free_balance(101), 2000);
+		assert_eq!(asset::stakeable_balance::<Test>(&11), 1000);
+		assert_eq!(asset::stakeable_balance::<Test>(&101), 2000);
 		assert_eq!(Staking::current_era().unwrap(), 2);
 		assert_eq!(active_era(), 2);
 
 		// no slash yet.
 		mock::start_active_era(3);
-		assert_eq!(Balances::free_balance(11), 1000);
-		assert_eq!(Balances::free_balance(101), 2000);
+		assert_eq!(asset::stakeable_balance::<Test>(&11), 1000);
+		assert_eq!(asset::stakeable_balance::<Test>(&101), 2000);
 		assert_eq!(Staking::current_era().unwrap(), 3);
 		assert_eq!(active_era(), 3);
 
@@ -3203,8 +3214,8 @@ fn staker_cannot_bail_deferred_slash() {
 		// after being deferred for at least 2 full eras.
 		mock::start_active_era(4);
 
-		assert_eq!(Balances::free_balance(11), 900);
-		assert_eq!(Balances::free_balance(101), 2000 - (nominated_value / 10));
+		assert_eq!(asset::stakeable_balance::<Test>(&11), 900);
+		assert_eq!(asset::stakeable_balance::<Test>(&101), 2000 - (nominated_value / 10));
 
 		// and the leftover of the funds can now be unbonded.
 	})
@@ -3215,10 +3226,10 @@ fn remove_deferred() {
 	ExtBuilder::default().slash_defer_duration(2).build_and_execute(|| {
 		mock::start_active_era(1);
 
-		assert_eq!(Balances::free_balance(11), 1000);
+		assert_eq!(asset::stakeable_balance::<Test>(&11), 1000);
 
 		let exposure = Staking::eras_stakers(active_era(), &11);
-		assert_eq!(Balances::free_balance(101), 2000);
+		assert_eq!(asset::stakeable_balance::<Test>(&101), 2000);
 		let nominated_value = exposure.others.iter().find(|o| o.who == 101).unwrap().value;
 
 		// deferred to start of era 4.
@@ -3227,8 +3238,8 @@ fn remove_deferred() {
 			&[Perbill::from_percent(10)],
 		);
 
-		assert_eq!(Balances::free_balance(11), 1000);
-		assert_eq!(Balances::free_balance(101), 2000);
+		assert_eq!(asset::stakeable_balance::<Test>(&11), 1000);
+		assert_eq!(asset::stakeable_balance::<Test>(&101), 2000);
 
 		mock::start_active_era(2);
 
@@ -3249,13 +3260,13 @@ fn remove_deferred() {
 		// cancel one of them.
 		assert_ok!(Staking::cancel_deferred_slash(RuntimeOrigin::root(), 4, vec![0]));
 
-		assert_eq!(Balances::free_balance(11), 1000);
-		assert_eq!(Balances::free_balance(101), 2000);
+		assert_eq!(asset::stakeable_balance::<Test>(&11), 1000);
+		assert_eq!(asset::stakeable_balance::<Test>(&101), 2000);
 
 		mock::start_active_era(3);
 
-		assert_eq!(Balances::free_balance(11), 1000);
-		assert_eq!(Balances::free_balance(101), 2000);
+		assert_eq!(asset::stakeable_balance::<Test>(&11), 1000);
+		assert_eq!(asset::stakeable_balance::<Test>(&101), 2000);
 
 		// at the start of era 4, slashes from era 1 are processed,
 		// after being deferred for at least 2 full eras.
@@ -3280,8 +3291,8 @@ fn remove_deferred() {
 		let actual_slash = total_slash - initial_slash;
 
 		// 5% slash (15 - 10) processed now.
-		assert_eq!(Balances::free_balance(11), 950);
-		assert_eq!(Balances::free_balance(101), 2000 - actual_slash);
+		assert_eq!(asset::stakeable_balance::<Test>(&11), 950);
+		assert_eq!(asset::stakeable_balance::<Test>(&101), 2000 - actual_slash);
 	})
 }
 
@@ -3290,10 +3301,10 @@ fn remove_multi_deferred() {
 	ExtBuilder::default().slash_defer_duration(2).build_and_execute(|| {
 		mock::start_active_era(1);
 
-		assert_eq!(Balances::free_balance(11), 1000);
+		assert_eq!(asset::stakeable_balance::<Test>(&11), 1000);
 
 		let exposure = Staking::eras_stakers(active_era(), &11);
-		assert_eq!(Balances::free_balance(101), 2000);
+		assert_eq!(asset::stakeable_balance::<Test>(&101), 2000);
 
 		on_offence_now(
 			&[OffenceDetails { offender: (11, exposure.clone()), reporters: vec![] }],
@@ -3363,8 +3374,8 @@ fn slash_kicks_validators_not_nominators_and_disables_nominator_for_kicked_valid
 			assert_eq_uvec!(Session::validators(), vec![11, 21, 31, 41, 51, 201, 202]);
 
 			// pre-slash balance
-			assert_eq!(Balances::free_balance(11), 1000);
-			assert_eq!(Balances::free_balance(101), 2000);
+			assert_eq!(asset::stakeable_balance::<Test>(&11), 1000);
+			assert_eq!(asset::stakeable_balance::<Test>(&101), 2000);
 
 			// 100 has approval for 11 as of now
 			assert!(Staking::nominators(101).unwrap().targets.contains(&11));
@@ -3398,8 +3409,8 @@ fn slash_kicks_validators_not_nominators_and_disables_nominator_for_kicked_valid
 
 			// post-slash balance
 			let nominator_slash_amount_11 = 125 / 10;
-			assert_eq!(Balances::free_balance(11), 900);
-			assert_eq!(Balances::free_balance(101), 2000 - nominator_slash_amount_11);
+			assert_eq!(asset::stakeable_balance::<Test>(&11), 900);
+			assert_eq!(asset::stakeable_balance::<Test>(&101), 2000 - nominator_slash_amount_11);
 
 			// check that validator was disabled.
 			assert!(is_disabled(11));
@@ -3663,8 +3674,8 @@ fn claim_reward_at_the_last_era_and_no_double_claim_and_invalid_claim() {
 		// Consumed weight for all payout_stakers dispatches that fail
 		let err_weight = <Test as Config>::WeightInfo::payout_stakers_alive_staked(0);
 
-		let init_balance_11 = Balances::total_balance(&11);
-		let init_balance_101 = Balances::total_balance(&101);
+		let init_balance_11 = asset::total_balance::<Test>(&11);
+		let init_balance_101 = asset::total_balance::<Test>(&101);
 
 		let part_for_11 = Perbill::from_rational::<u32>(1000, 1125);
 		let part_for_101 = Perbill::from_rational::<u32>(125, 1125);
@@ -3728,11 +3739,11 @@ fn claim_reward_at_the_last_era_and_no_double_claim_and_invalid_claim() {
 		// only era 1 and 2 can be rewarded.
 
 		assert_eq!(
-			Balances::total_balance(&11),
+			asset::total_balance::<Test>(&11),
 			init_balance_11 + part_for_11 * (total_payout_1 + total_payout_2),
 		);
 		assert_eq!(
-			Balances::total_balance(&101),
+			asset::total_balance::<Test>(&101),
 			init_balance_101 + part_for_101 * (total_payout_1 + total_payout_2),
 		);
 	});
@@ -3749,18 +3760,18 @@ fn zero_slash_keeps_nominators() {
 		.build_and_execute(|| {
 			mock::start_active_era(1);
 
-			assert_eq!(Balances::free_balance(11), 1000);
+			assert_eq!(asset::stakeable_balance::<Test>(&11), 1000);
 
 			let exposure = Staking::eras_stakers(active_era(), &11);
-			assert_eq!(Balances::free_balance(101), 2000);
+			assert_eq!(asset::stakeable_balance::<Test>(&101), 2000);
 
 			on_offence_now(
 				&[OffenceDetails { offender: (11, exposure.clone()), reporters: vec![] }],
 				&[Perbill::from_percent(0)],
 			);
 
-			assert_eq!(Balances::free_balance(11), 1000);
-			assert_eq!(Balances::free_balance(101), 2000);
+			assert_eq!(asset::stakeable_balance::<Test>(&11), 1000);
+			assert_eq!(asset::stakeable_balance::<Test>(&101), 2000);
 
 			// 11 is not removed but disabled
 			assert!(Validators::<Test>::iter().any(|(stash, _)| stash == 11));
@@ -3837,7 +3848,7 @@ fn test_nominators_over_max_exposure_page_size_are_rewarded() {
 		for i in 0..=MaxExposurePageSize::get() {
 			let stash = 10_000 + i as AccountId;
 			let balance = 10_000 + i as Balance;
-			Balances::make_free_balance_be(&stash, balance);
+			asset::set_stakeable_balance::<Test>(&stash, balance);
 			assert_ok!(Staking::bond(
 				RuntimeOrigin::signed(stash),
 				balance,
@@ -3859,13 +3870,13 @@ fn test_nominators_over_max_exposure_page_size_are_rewarded() {
 		while i < MaxExposurePageSize::get() {
 			let stash = 10_000 + i as AccountId;
 			let balance = 10_000 + i as Balance;
-			assert!(Balances::free_balance(&stash) > balance);
+			assert!(asset::stakeable_balance::<Test>(&stash) > balance);
 			i += 1;
 		}
 
 		// Assert overflowing nominators from page 1 are also rewarded
 		let stash = 10_000 + i as AccountId;
-		assert!(Balances::free_balance(&stash) > (10_000 + i) as Balance);
+		assert!(asset::stakeable_balance::<Test>(&stash) > (10_000 + i) as Balance);
 	});
 }
 
@@ -3878,7 +3889,7 @@ fn test_nominators_are_rewarded_for_all_exposure_page() {
 		for i in 0..nominator_count {
 			let stash = 10_000 + i as AccountId;
 			let balance = 10_000 + i as Balance;
-			Balances::make_free_balance_be(&stash, balance);
+			asset::set_stakeable_balance::<Test>(&stash, balance);
 			assert_ok!(Staking::bond(
 				RuntimeOrigin::signed(stash),
 				balance,
@@ -3900,9 +3911,10 @@ fn test_nominators_are_rewarded_for_all_exposure_page() {
 		// Assert all nominators are rewarded according to their stake
 		for i in 0..nominator_count {
 			// balance of the nominator after the reward payout.
-			let current_balance = Balances::free_balance(&((10000 + i) as AccountId));
+			let current_balance = asset::stakeable_balance::<Test>(&((10000 + i) as AccountId));
 			// balance of the nominator in the previous iteration.
-			let previous_balance = Balances::free_balance(&((10000 + i - 1) as AccountId));
+			let previous_balance =
+				asset::stakeable_balance::<Test>(&((10000 + i - 1) as AccountId));
 			// balance before the reward.
 			let original_balance = 10_000 + i as Balance;
 
@@ -3958,7 +3970,7 @@ fn test_multi_page_payout_stakers_by_page() {
 		RewardOnUnbalanceWasCalled::set(false);
 		System::reset_events();
 
-		let controller_balance_before_p0_payout = Balances::free_balance(&11);
+		let controller_balance_before_p0_payout = asset::stakeable_balance::<Test>(&11);
 		// Payout rewards for first exposure page
 		assert_ok!(Staking::payout_stakers_by_page(RuntimeOrigin::signed(1337), 11, 1, 0));
 
@@ -3972,7 +3984,7 @@ fn test_multi_page_payout_stakers_by_page() {
 			]
 		));
 
-		let controller_balance_after_p0_payout = Balances::free_balance(&11);
+		let controller_balance_after_p0_payout = asset::stakeable_balance::<Test>(&11);
 
 		// verify rewards have been paid out but still some left
 		assert!(pallet_balances::TotalIssuance::<Test>::get() > pre_payout_total_issuance);
@@ -3996,7 +4008,7 @@ fn test_multi_page_payout_stakers_by_page() {
 			]
 		));
 		// verify the validator was not rewarded the second time
-		assert_eq!(Balances::free_balance(&11), controller_balance_after_p0_payout);
+		assert_eq!(asset::stakeable_balance::<Test>(&11), controller_balance_after_p0_payout);
 
 		// verify all rewards have been paid out
 		assert_eq_error_rate!(
@@ -4007,9 +4019,9 @@ fn test_multi_page_payout_stakers_by_page() {
 		assert!(RewardOnUnbalanceWasCalled::get());
 
 		// Top 64 nominators of validator 11 automatically paid out, including the validator
-		assert!(Balances::free_balance(&11) > balance);
+		assert!(asset::stakeable_balance::<Test>(&11) > balance);
 		for i in 0..100 {
-			assert!(Balances::free_balance(&(1000 + i)) > balance + i as Balance);
+			assert!(asset::stakeable_balance::<Test>(&(1000 + i)) > balance + i as Balance);
 		}
 
 		// verify we no longer track rewards in `legacy_claimed_rewards` vec
@@ -4178,7 +4190,7 @@ fn test_multi_page_payout_stakers_backward_compatible() {
 		let pre_payout_total_issuance = pallet_balances::TotalIssuance::<Test>::get();
 		RewardOnUnbalanceWasCalled::set(false);
 
-		let controller_balance_before_p0_payout = Balances::free_balance(&11);
+		let controller_balance_before_p0_payout = asset::stakeable_balance::<Test>(&11);
 		// Payout rewards for first exposure page
 		assert_ok!(Staking::payout_stakers(RuntimeOrigin::signed(1337), 11, 1));
 		// page 0 is claimed
@@ -4187,7 +4199,7 @@ fn test_multi_page_payout_stakers_backward_compatible() {
 			Error::<Test>::AlreadyClaimed.with_weight(err_weight)
 		);
 
-		let controller_balance_after_p0_payout = Balances::free_balance(&11);
+		let controller_balance_after_p0_payout = asset::stakeable_balance::<Test>(&11);
 
 		// verify rewards have been paid out but still some left
 		assert!(pallet_balances::TotalIssuance::<Test>::get() > pre_payout_total_issuance);
@@ -4206,7 +4218,7 @@ fn test_multi_page_payout_stakers_backward_compatible() {
 		);
 
 		// verify the validator was not rewarded the second time
-		assert_eq!(Balances::free_balance(&11), controller_balance_after_p0_payout);
+		assert_eq!(asset::stakeable_balance::<Test>(&11), controller_balance_after_p0_payout);
 
 		// verify all rewards have been paid out
 		assert_eq_error_rate!(
@@ -4218,9 +4230,9 @@ fn test_multi_page_payout_stakers_backward_compatible() {
 
 		// verify all nominators of validator 11 are paid out, including the validator
 		// Validator payout goes to controller.
-		assert!(Balances::free_balance(&11) > balance);
+		assert!(asset::stakeable_balance::<Test>(&11) > balance);
 		for i in 0..100 {
-			assert!(Balances::free_balance(&(1000 + i)) > balance + i as Balance);
+			assert!(asset::stakeable_balance::<Test>(&(1000 + i)) > balance + i as Balance);
 		}
 
 		// verify we no longer track rewards in `legacy_claimed_rewards` vec
@@ -4578,25 +4590,29 @@ fn test_commission_paid_across_pages() {
 		let payout = current_total_payout_for_duration(reward_time_per_era());
 		mock::start_active_era(2);
 
-		let initial_balance = Balances::free_balance(&11);
+		let initial_balance = asset::stakeable_balance::<Test>(&11);
 		// Payout rewards for first exposure page
 		assert_ok!(Staking::payout_stakers_by_page(RuntimeOrigin::signed(1337), 11, 1, 0));
 
-		let controller_balance_after_p0_payout = Balances::free_balance(&11);
+		let controller_balance_after_p0_payout = asset::stakeable_balance::<Test>(&11);
 
 		// some commission is paid
 		assert!(initial_balance < controller_balance_after_p0_payout);
 
 		// payout all pages
 		for i in 1..4 {
-			let before_balance = Balances::free_balance(&11);
+			let before_balance = asset::stakeable_balance::<Test>(&11);
 			assert_ok!(Staking::payout_stakers_by_page(RuntimeOrigin::signed(1337), 11, 1, i));
-			let after_balance = Balances::free_balance(&11);
+			let after_balance = asset::stakeable_balance::<Test>(&11);
 			// some commission is paid for every page
 			assert!(before_balance < after_balance);
 		}
 
-		assert_eq_error_rate!(Balances::free_balance(&11), initial_balance + payout / 2, 1,);
+		assert_eq_error_rate!(
+			asset::stakeable_balance::<Test>(&11),
+			initial_balance + payout / 2,
+			1,
+		);
 	});
 }
 
@@ -4852,7 +4868,7 @@ fn payout_to_any_account_works() {
 		assert_ok!(Staking::set_payee(RuntimeOrigin::signed(1234), RewardDestination::Account(42)));
 
 		// Reward Destination account doesn't exist
-		assert_eq!(Balances::free_balance(42), 0);
+		assert_eq!(asset::stakeable_balance::<Test>(&42), 0);
 
 		mock::start_active_era(1);
 		Staking::reward_by_ids(vec![(11, 1)]);
@@ -4862,7 +4878,7 @@ fn payout_to_any_account_works() {
 		assert_ok!(Staking::payout_stakers_by_page(RuntimeOrigin::signed(1337), 11, 1, 0));
 
 		// Payment is successful
-		assert!(Balances::free_balance(42) > 0);
+		assert!(asset::stakeable_balance::<Test>(&42) > 0);
 	})
 }
 
@@ -5661,9 +5677,9 @@ fn chill_other_works() {
 				let a = 4 * i;
 				let b = 4 * i + 2;
 				let c = 4 * i + 3;
-				Balances::make_free_balance_be(&a, 100_000);
-				Balances::make_free_balance_be(&b, 100_000);
-				Balances::make_free_balance_be(&c, 100_000);
+				asset::set_stakeable_balance::<Test>(&a, 100_000);
+				asset::set_stakeable_balance::<Test>(&b, 100_000);
+				asset::set_stakeable_balance::<Test>(&c, 100_000);
 
 				// Nominator
 				assert_ok!(Staking::bond(RuntimeOrigin::signed(a), 1000, RewardDestination::Stash));
@@ -6859,7 +6875,7 @@ fn test_runtime_api_pending_rewards() {
 
 		// Set staker
 		for v in validator_one..=validator_three {
-			let _ = Balances::make_free_balance_be(&v, stake);
+			let _ = asset::set_stakeable_balance::<Test>(&v, stake);
 			assert_ok!(Staking::bond(RuntimeOrigin::signed(v), stake, RewardDestination::Staked));
 		}
 
@@ -7049,7 +7065,7 @@ mod staking_interface {
 				assert!(!<Validators<Test>>::contains_key(&11));
 				assert!(!<Payee<Test>>::contains_key(&11));
 				// lock is removed.
-				assert_eq!(Balances::balance_locked(STAKING_ID, &11), 0);
+				assert_eq!(asset::staked::<Test>(&11), 0);
 			});
 	}
 
@@ -7086,12 +7102,12 @@ mod staking_unchecked {
 	fn virtual_bond_does_not_lock() {
 		ExtBuilder::default().build_and_execute(|| {
 			mock::start_active_era(1);
-			assert_eq!(Balances::free_balance(10), 1);
+			assert_eq!(asset::stakeable_balance::<Test>(&10), 1);
 			// 10 can bond more than its balance amount since we do not require lock for virtual
 			// bonding.
 			assert_ok!(<Staking as StakingUnchecked>::virtual_bond(&10, 100, &15));
 			// nothing is locked on 10.
-			assert_eq!(Balances::balance_locked(STAKING_ID, &10), 0);
+			assert_eq!(asset::staked::<Test>(&10), 0);
 			// adding more balance does not lock anything as well.
 			assert_ok!(<Staking as StakingInterface>::bond_extra(&10, 1000));
 			// but ledger is updated correctly.
@@ -7118,7 +7134,7 @@ mod staking_unchecked {
 				Ok(Stake { total: 1100, active: 900 })
 			);
 			// still no locks.
-			assert_eq!(Balances::balance_locked(STAKING_ID, &10), 0);
+			assert_eq!(asset::staked::<Test>(&10), 0);
 
 			mock::start_active_era(2);
 			// cannot withdraw without waiting for unbonding period.
@@ -7218,11 +7234,11 @@ mod staking_unchecked {
 	fn migrate_virtual_staker() {
 		ExtBuilder::default().build_and_execute(|| {
 			// give some balance to 200
-			Balances::make_free_balance_be(&200, 2000);
+			asset::set_stakeable_balance::<Test>(&200, 2000);
 
 			// stake
 			assert_ok!(Staking::bond(RuntimeOrigin::signed(200), 1000, RewardDestination::Staked));
-			assert_eq!(Balances::balance_locked(crate::STAKING_ID, &200), 1000);
+			assert_eq!(asset::staked::<Test>(&200), 1000);
 
 			// migrate them to virtual staker
 			<Staking as StakingUnchecked>::migrate_to_virtual_staker(&200);
@@ -7230,7 +7246,7 @@ mod staking_unchecked {
 			assert_ok!(<Staking as StakingInterface>::set_payee(&200, &201));
 
 			// ensure the balance is not locked anymore
-			assert_eq!(Balances::balance_locked(crate::STAKING_ID, &200), 0);
+			assert_eq!(asset::staked::<Test>(&200), 0);
 
 			// and they are marked as virtual stakers
 			assert_eq!(Pallet::<Test>::is_virtual_staker(&200), true);
@@ -7300,7 +7316,7 @@ mod staking_unchecked {
 				assert!(is_disabled(11));
 
 				// but virtual nominator's balance is not slashed.
-				assert_eq!(Balances::free_balance(&101), nominator_balance);
+				assert_eq!(asset::stakeable_balance::<Test>(&101), nominator_balance);
 				// but slash is broadcasted to slash observers.
 				assert_eq!(SlashObserver::get().get(&101).unwrap(), &nominator_share);
 			})
@@ -7332,9 +7348,9 @@ mod staking_unchecked {
 				assert_ok!(<Staking as StakingInterface>::set_payee(&101, &102));
 
 				// cache values
-				let validator_balance = Balances::free_balance(&11);
+				let validator_balance = asset::stakeable_balance::<Test>(&11);
 				let validator_stake = Staking::ledger(11.into()).unwrap().total;
-				let nominator_balance = Balances::free_balance(&101);
+				let nominator_balance = asset::stakeable_balance::<Test>(&101);
 				let nominator_stake = Staking::ledger(101.into()).unwrap().total;
 
 				// 11 goes offline
@@ -7353,14 +7369,14 @@ mod staking_unchecked {
 				// all validator stake is slashed
 				assert_eq_error_rate!(
 					validator_balance - validator_stake,
-					Balances::free_balance(&11),
+					asset::stakeable_balance::<Test>(&11),
 					1
 				);
 				// Because slashing happened.
 				assert!(is_disabled(11));
 
 				// Virtual nominator's balance is not slashed.
-				assert_eq!(Balances::free_balance(&101), nominator_balance);
+				assert_eq!(asset::stakeable_balance::<Test>(&101), nominator_balance);
 				// Slash is broadcasted to slash observers.
 				assert_eq!(SlashObserver::get().get(&101).unwrap(), &nominator_stake);
 
@@ -7900,7 +7916,7 @@ mod ledger_recovery {
 		ExtBuilder::default().has_stakers(true).try_state(false).build_and_execute(|| {
 			setup_double_bonded_ledgers();
 
-			let lock_333_before = Balances::balance_locked(crate::STAKING_ID, &333);
+			let lock_333_before = asset::staked::<Test>(&333);
 
 			// get into corrupted and killed ledger state by killing a corrupted ledger:
 			// init state:
@@ -7936,14 +7952,14 @@ mod ledger_recovery {
 
 			// side effects on 333 - ledger, bonded, payee, lock should be completely empty.
 			// however, 333 lock remains.
-			assert_eq!(Balances::balance_locked(crate::STAKING_ID, &333), lock_333_before); // NOK
+			assert_eq!(asset::staked::<Test>(&333), lock_333_before); // NOK
 			assert!(Bonded::<Test>::get(&333).is_none()); // OK
 			assert!(Payee::<Test>::get(&333).is_none()); // OK
 			assert!(Ledger::<Test>::get(&444).is_none()); // OK
 
 			// side effects on 444 - ledger, bonded, payee, lock should remain be intact.
 			// however, 444 lock was removed.
-			assert_eq!(Balances::balance_locked(crate::STAKING_ID, &444), 0); // NOK
+			assert_eq!(asset::staked::<Test>(&444), 0); // NOK
 			assert!(Bonded::<Test>::get(&444).is_some()); // OK
 			assert!(Payee::<Test>::get(&444).is_some()); // OK
 			assert!(Ledger::<Test>::get(&555).is_none()); // NOK
@@ -7957,7 +7973,7 @@ mod ledger_recovery {
 		ExtBuilder::default().has_stakers(true).try_state(false).build_and_execute(|| {
 			setup_double_bonded_ledgers();
 
-			let lock_333_before = Balances::balance_locked(crate::STAKING_ID, &333);
+			let lock_333_before = asset::staked::<Test>(&333);
 
 			// get into corrupted and killed ledger state by killing a corrupted ledger:
 			// init state:
@@ -7992,14 +8008,14 @@ mod ledger_recovery {
 			assert_eq!(Staking::inspect_bond_state(&444), Err(Error::<Test>::NotStash));
 
 			// side effects on 333 - ledger, bonded, payee, lock should be intact.
-			assert_eq!(Balances::balance_locked(crate::STAKING_ID, &333), lock_333_before); // OK
+			assert_eq!(asset::staked::<Test>(&333), lock_333_before); // OK
 			assert_eq!(Bonded::<Test>::get(&333), Some(444)); // OK
 			assert!(Payee::<Test>::get(&333).is_some()); // OK
 												// however, ledger associated with its controller was killed.
 			assert!(Ledger::<Test>::get(&444).is_none()); // NOK
 
 			// side effects on 444 - ledger, bonded, payee, lock should be completely removed.
-			assert_eq!(Balances::balance_locked(crate::STAKING_ID, &444), 0); // OK
+			assert_eq!(asset::staked::<Test>(&444), 0); // OK
 			assert!(Bonded::<Test>::get(&444).is_none()); // OK
 			assert!(Payee::<Test>::get(&444).is_none()); // OK
 			assert!(Ledger::<Test>::get(&555).is_none()); // OK
@@ -8080,7 +8096,7 @@ mod ledger_recovery {
 			setup_double_bonded_ledgers();
 
 			// ledger.total == lock
-			let total_444_before_corruption = Balances::balance_locked(crate::STAKING_ID, &444);
+			let total_444_before_corruption = asset::staked::<Test>(&444);
 
 			// get into corrupted and killed ledger state by killing a corrupted ledger:
 			// init state:
@@ -8182,8 +8198,8 @@ mod ledger_recovery {
 		ExtBuilder::default().has_stakers(true).build_and_execute(|| {
 			setup_double_bonded_ledgers();
 
-			let lock_333_before = Balances::balance_locked(crate::STAKING_ID, &333);
-			let lock_444_before = Balances::balance_locked(crate::STAKING_ID, &444);
+			let lock_333_before = asset::staked::<Test>(&333);
+			let lock_444_before = asset::staked::<Test>(&444);
 
 			// get into corrupted and killed ledger state by killing a corrupted ledger:
 			// init state:
@@ -8203,16 +8219,13 @@ mod ledger_recovery {
 
 			// if 444 bonds extra, the locks remain in sync.
 			bond_extra_no_checks(&444, 40);
-			assert_eq!(Balances::balance_locked(crate::STAKING_ID, &333), lock_333_before);
-			assert_eq!(Balances::balance_locked(crate::STAKING_ID, &444), lock_444_before + 40);
+			assert_eq!(asset::staked::<Test>(&333), lock_333_before);
+			assert_eq!(asset::staked::<Test>(&444), lock_444_before + 40);
 
 			// however if 333 bonds extra, the wrong lock is updated.
 			bond_extra_no_checks(&333, 30);
-			assert_eq!(
-				Balances::balance_locked(crate::STAKING_ID, &333),
-				lock_444_before + 40 + 30
-			); //not OK
-			assert_eq!(Balances::balance_locked(crate::STAKING_ID, &444), lock_444_before + 40); // OK
+			assert_eq!(asset::staked::<Test>(&333), lock_444_before + 40 + 30); //not OK
+			assert_eq!(asset::staked::<Test>(&444), lock_444_before + 40); // OK
 
 			// recover the ledger bonded by 333 stash. Note that the total/lock needs to be
 			// re-written since on-chain data lock has become out of sync.
@@ -8247,9 +8260,9 @@ mod ledger_recovery {
 			let ledger_444 = Bonded::<Test>::get(&444).and_then(Ledger::<Test>::get).unwrap();
 
 			assert_eq!(ledger_333.total, lock_333_before + 30);
-			assert_eq!(Balances::balance_locked(crate::STAKING_ID, &333), ledger_333.total);
+			assert_eq!(asset::staked::<Test>(&333), ledger_333.total);
 			assert_eq!(ledger_444.total, lock_444_before + 40);
-			assert_eq!(Balances::balance_locked(crate::STAKING_ID, &444), ledger_444.total);
+			assert_eq!(asset::staked::<Test>(&444), ledger_444.total);
 
 			// try-state checks are ok now.
 			assert_ok!(Staking::do_try_state(System::block_number()));
diff --git a/substrate/primitives/staking/src/lib.rs b/substrate/primitives/staking/src/lib.rs
index 5e94524816a..17010a8907f 100644
--- a/substrate/primitives/staking/src/lib.rs
+++ b/substrate/primitives/staking/src/lib.rs
@@ -619,7 +619,7 @@ pub trait DelegationMigrator {
 	///
 	/// Also removed from [`StakingUnchecked`] as a Virtual Staker. Useful for testing.
 	#[cfg(feature = "runtime-benchmarks")]
-	fn migrate_to_direct_staker(agent: Agent<Self::AccountId>);
+	fn force_kill_agent(agent: Agent<Self::AccountId>);
 }
 
 sp_core::generate_feature_enabled_macro!(runtime_benchmarks_enabled, feature = "runtime-benchmarks", $);
-- 
GitLab