From fdec1b0e0dbfd4ffa74788512998627a74174579 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 559baf76e4c6..e9131a82e4ea 100644 --- a/substrate/frame/nomination-pools/src/migration.rs +++ b/substrate/frame/nomination-pools/src/migration.rs @@ -149,6 +149,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. @@ -207,7 +213,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(); @@ -224,6 +230,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 386f5a69c3d3ba8057e9cdf29175a10c620d9f11 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 e9131a82e4ea..5231de3f8847 100644 --- a/substrate/frame/nomination-pools/src/migration.rs +++ b/substrate/frame/nomination-pools/src/migration.rs @@ -150,6 +150,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()); @@ -243,6 +244,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) } @@ -265,6 +267,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; @@ -292,6 +295,7 @@ pub(crate) mod v7 { active_balance + unbonding_balance } + #[allow(dead_code)] fn point_to_balance( current_balance: BalanceOf, current_points: BalanceOf,