diff --git a/prdoc/pr_2796.prdoc b/prdoc/pr_2796.prdoc
index 15cb005d286f9b5f57eac275561f0892cc246509..0530c9ad7140f9fc5d0b9b41129910b09f074c48 100644
--- a/prdoc/pr_2796.prdoc
+++ b/prdoc/pr_2796.prdoc
@@ -1,4 +1,4 @@
-title: Rococo and Westend Asset-Hub: XCM Transfers with Pallet-Uniques
+title: "Rococo and Westend Asset-Hub: XCM Transfers with Pallet-Uniques"
 
 doc:
   - audience: Runtime User
diff --git a/prdoc/pr_2920.prdoc b/prdoc/pr_2920.prdoc
index 7745838ab5c0c08cb499f3691fa0d1dd712e4106..d41227ee8b8a4abb8f9c4bf7c2d1946278e89ecd 100644
--- a/prdoc/pr_2920.prdoc
+++ b/prdoc/pr_2920.prdoc
@@ -1,11 +1,12 @@
 # Schema: Polkadot SDK PRDoc Schema (prdoc) v1.0.0
 # See doc at https://raw.githubusercontent.com/paritytech/polkadot-sdk/master/prdoc/schema_user.json
 
-title: Contracts: Stabilize sr25519_verify host function
+title: "Contracts: Stabilize sr25519_verify host function"
 
 doc:
   - audience: Runtime Dev
     description: |
       Removed the `#[unstable]` attrribute on `sr25519_verify` host function.
 
-crates: ["pallet-contracts"]
+crates:
+  - name: "pallet-contracts"
diff --git a/prdoc/pr_2942.prdoc b/prdoc/pr_2942.prdoc
new file mode 100644
index 0000000000000000000000000000000000000000..caa276c099b395371025a23aa76734b186a1675e
--- /dev/null
+++ b/prdoc/pr_2942.prdoc
@@ -0,0 +1,13 @@
+# Schema: Polkadot SDK PRDoc Schema (prdoc) v1.0.0
+# See doc at https://raw.githubusercontent.com/paritytech/polkadot-sdk/master/prdoc/schema_user.json
+
+title: Fix pallet-nomination-pools v6 to v7 migration
+
+doc:
+  - audience: Node Dev
+    description: |
+      Restores the behaviour of the nomination pools `V6ToV7` migration so that it still works when
+      the pallet will be upgraded to V8 afterwards.
+
+crates:
+  - name: "pallet-nomination-pools"
diff --git a/substrate/frame/nomination-pools/src/migration.rs b/substrate/frame/nomination-pools/src/migration.rs
index 3adfd926d95cf7e90994597263db2e17d36f3978..559baf76e4c64c5893d44c15d3505a9083ed76db 100644
--- a/substrate/frame/nomination-pools/src/migration.rs
+++ b/substrate/frame/nomination-pools/src/migration.rs
@@ -57,26 +57,9 @@ pub mod versioned {
 }
 
 pub mod v8 {
-	use super::*;
-
-	#[derive(Decode)]
-	pub struct OldCommission<T: Config> {
-		pub current: Option<(Perbill, T::AccountId)>,
-		pub max: Option<Perbill>,
-		pub change_rate: Option<CommissionChangeRate<BlockNumberFor<T>>>,
-		pub throttle_from: Option<BlockNumberFor<T>>,
-	}
-
-	#[derive(Decode)]
-	pub struct OldBondedPoolInner<T: Config> {
-		pub commission: OldCommission<T>,
-		pub member_counter: u32,
-		pub points: BalanceOf<T>,
-		pub roles: PoolRoles<T::AccountId>,
-		pub state: PoolState,
-	}
+	use super::{v7::V7BondedPoolInner, *};
 
-	impl<T: Config> OldBondedPoolInner<T> {
+	impl<T: Config> V7BondedPoolInner<T> {
 		fn migrate_to_v8(self) -> BondedPoolInner<T> {
 			BondedPoolInner {
 				commission: Commission {
@@ -104,7 +87,7 @@ pub mod v8 {
 
 		fn on_runtime_upgrade() -> Weight {
 			let mut translated = 0u64;
-			BondedPools::<T>::translate::<OldBondedPoolInner<T>, _>(|_key, old_value| {
+			BondedPools::<T>::translate::<V7BondedPoolInner<T>, _>(|_key, old_value| {
 				translated.saturating_inc();
 				Some(old_value.migrate_to_v8())
 			});
@@ -128,16 +111,58 @@ pub mod v8 {
 ///
 /// WARNING: This migration works under the assumption that the [`BondedPools`] cannot be inflated
 /// arbitrarily. Otherwise this migration could fail due to too high weight.
-mod v7 {
+pub(crate) mod v7 {
 	use super::*;
 
+	#[derive(Encode, Decode, MaxEncodedLen, TypeInfo, DebugNoBound, PartialEq, Clone)]
+	#[codec(mel_bound(T: Config))]
+	#[scale_info(skip_type_params(T))]
+	pub struct V7Commission<T: Config> {
+		pub current: Option<(Perbill, T::AccountId)>,
+		pub max: Option<Perbill>,
+		pub change_rate: Option<CommissionChangeRate<BlockNumberFor<T>>>,
+		pub throttle_from: Option<BlockNumberFor<T>>,
+	}
+
+	#[derive(Encode, Decode, MaxEncodedLen, TypeInfo, DebugNoBound, PartialEq, Clone)]
+	#[codec(mel_bound(T: Config))]
+	#[scale_info(skip_type_params(T))]
+	pub struct V7BondedPoolInner<T: Config> {
+		pub commission: V7Commission<T>,
+		pub member_counter: u32,
+		pub points: BalanceOf<T>,
+		pub roles: PoolRoles<T::AccountId>,
+		pub state: PoolState,
+	}
+
+	#[allow(dead_code)]
+	#[derive(RuntimeDebugNoBound)]
+	#[cfg_attr(feature = "std", derive(Clone, PartialEq))]
+	pub struct V7BondedPool<T: Config> {
+		/// The identifier of the pool.
+		id: PoolId,
+		/// The inner fields.
+		inner: V7BondedPoolInner<T>,
+	}
+
+	impl<T: Config> V7BondedPool<T> {
+		fn bonded_account(&self) -> T::AccountId {
+			Pallet::<T>::create_bonded_account(self.id)
+		}
+	}
+
+	// NOTE: We cannot put a V7 prefix here since that would change the storage key.
+	#[frame_support::storage_alias]
+	pub type BondedPools<T: Config> =
+		CountedStorageMap<Pallet<T>, Twox64Concat, PoolId, V7BondedPoolInner<T>>;
+
 	pub struct VersionUncheckedMigrateV6ToV7<T>(sp_std::marker::PhantomData<T>);
 	impl<T: Config> VersionUncheckedMigrateV6ToV7<T> {
 		fn calculate_tvl_by_total_stake() -> BalanceOf<T> {
 			BondedPools::<T>::iter()
 				.map(|(id, inner)| {
 					T::Staking::total_stake(
-						&BondedPool { id, inner: inner.clone() }.bonded_account(),
+						&V7BondedPool { id, inner: inner.clone() }.bonded_account(),
 					)
 					.unwrap_or_default()
 				})