From a140589a8a0ce38c6e77bafd76e505a897cc31b9 Mon Sep 17 00:00:00 2001 From: Branislav Kontur Date: Tue, 13 Feb 2024 12:17:35 +0100 Subject: [PATCH 1/2] [nomination-pools] Backwards fix for `post_upgrade` migration V6ToV7 --- .../frame/nomination-pools/src/migration.rs | 90 ++++++++++++++++++- 1 file changed, 89 insertions(+), 1 deletion(-) diff --git a/substrate/frame/nomination-pools/src/migration.rs b/substrate/frame/nomination-pools/src/migration.rs index 6887fcfa7eca..296545fed3ed 100644 --- a/substrate/frame/nomination-pools/src/migration.rs +++ b/substrate/frame/nomination-pools/src/migration.rs @@ -203,6 +203,12 @@ pub(crate) mod v7 { fn bonded_account(&self) -> T::AccountId { Pallet::::create_bonded_account(self.id) } + + fn points_to_balance(&self, points: BalanceOf) -> BalanceOf { + let bonded_balance = + T::Staking::active_stake(&self.bonded_account()).unwrap_or(Zero::zero()); + point_to_balance::(bonded_balance, self.inner.points, points) + } } // NOTE: We cannot put a V7 prefix here since that would change the storage key. @@ -247,7 +253,7 @@ pub(crate) mod v7 { // calculate the sum of `total_balance` of all `PoolMember` as the upper bound for the // `TotalValueLocked`. let total_balance_members: BalanceOf = PoolMembers::::iter() - .map(|(_, member)| member.total_balance()) + .map(|(_, member)| total_balance(&member)) .reduce(|acc, total_balance| acc + total_balance) .unwrap_or_default(); @@ -264,6 +270,88 @@ pub(crate) mod v7 { Ok(()) } } + + #[derive(Encode, Decode, MaxEncodedLen, TypeInfo, DefaultNoBound, RuntimeDebugNoBound)] + #[cfg_attr(feature = "std", derive(Clone, PartialEq, Eq))] + #[codec(mel_bound(T: Config))] + #[scale_info(skip_type_params(T))] + pub struct UnbondPool { + /// The points in this pool. + points: BalanceOf, + /// The funds in the pool. + balance: BalanceOf, + } + + impl UnbondPool { + fn point_to_balance(&self, points: BalanceOf) -> BalanceOf { + point_to_balance::(self.balance, self.points, points) + } + } + + #[derive(Encode, Decode, MaxEncodedLen, TypeInfo, DefaultNoBound, RuntimeDebugNoBound)] + #[cfg_attr(feature = "std", derive(Clone, PartialEq))] + #[codec(mel_bound(T: Config))] + #[scale_info(skip_type_params(T))] + pub struct SubPools { + /// A general, era agnostic pool of funds that have fully unbonded. The pools + /// of `Self::with_era` will lazily be merged into into this pool if they are + /// older then `current_era - TotalUnbondingPools`. + no_era: UnbondPool, + /// Map of era in which a pool becomes unbonded in => unbond pools. + with_era: BoundedBTreeMap, TotalUnbondingPools>, + } + + #[frame_support::storage_alias] + pub type SubPoolsStorage = + CountedStorageMap, Twox64Concat, PoolId, SubPools>; + + fn total_balance(self_as_member: &PoolMember) -> BalanceOf { + // let pool = V7BondedPool::::get(self_as_member.pool_id).unwrap(); + let id = self_as_member.pool_id; + let pool = BondedPools::::try_get(id) + .ok() + .map(|inner| V7BondedPool { id, inner }) + .unwrap(); + let active_balance = pool.points_to_balance(self_as_member.points); + + let sub_pools = match SubPoolsStorage::::get(self_as_member.pool_id) { + Some(sub_pools) => sub_pools, + None => return active_balance, + }; + + let unbonding_balance = self_as_member.unbonding_eras.iter().fold( + BalanceOf::::zero(), + |accumulator, (era, unlocked_points)| { + // if the `SubPools::with_era` has already been merged into the + // `SubPools::no_era` use this pool instead. + let era_pool = sub_pools.with_era.get(era).unwrap_or(&sub_pools.no_era); + accumulator + (era_pool.point_to_balance(*unlocked_points)) + }, + ); + + active_balance + unbonding_balance + } + + fn point_to_balance( + current_balance: BalanceOf, + current_points: BalanceOf, + points: BalanceOf, + ) -> BalanceOf { + let u256 = T::BalanceToU256::convert; + let balance = T::U256ToBalance::convert; + if current_balance.is_zero() || current_points.is_zero() || points.is_zero() { + // There is nothing to unbond + return Zero::zero() + } + + // Equivalent of (current_balance / current_points) * points + balance( + u256(current_balance) + .saturating_mul(u256(points)) + // We check for zero above + .div(u256(current_points)), + ) + } } mod v6 { From a8472a910253f28fc95dde8664c18742004ccca8 Mon Sep 17 00:00:00 2001 From: Branislav Kontur Date: Tue, 13 Feb 2024 12:53:46 +0100 Subject: [PATCH 2/2] Fix warning dead_code --- substrate/frame/nomination-pools/src/migration.rs | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/substrate/frame/nomination-pools/src/migration.rs b/substrate/frame/nomination-pools/src/migration.rs index 296545fed3ed..b1066816ce7b 100644 --- a/substrate/frame/nomination-pools/src/migration.rs +++ b/substrate/frame/nomination-pools/src/migration.rs @@ -204,6 +204,7 @@ pub(crate) mod v7 { Pallet::::create_bonded_account(self.id) } + #[allow(dead_code)] fn points_to_balance(&self, points: BalanceOf) -> BalanceOf { let bonded_balance = T::Staking::active_stake(&self.bonded_account()).unwrap_or(Zero::zero()); @@ -283,6 +284,7 @@ pub(crate) mod v7 { } impl UnbondPool { + #[allow(dead_code)] fn point_to_balance(&self, points: BalanceOf) -> BalanceOf { point_to_balance::(self.balance, self.points, points) } @@ -305,6 +307,7 @@ pub(crate) mod v7 { pub type SubPoolsStorage = CountedStorageMap, Twox64Concat, PoolId, SubPools>; + #[allow(dead_code)] fn total_balance(self_as_member: &PoolMember) -> BalanceOf { // let pool = V7BondedPool::::get(self_as_member.pool_id).unwrap(); let id = self_as_member.pool_id; @@ -332,6 +335,7 @@ pub(crate) mod v7 { active_balance + unbonding_balance } + #[allow(dead_code)] fn point_to_balance( current_balance: BalanceOf, current_points: BalanceOf,