diff --git a/libs/types/src/tokens.rs b/libs/types/src/tokens.rs index 02051f2393..12c9b7d58b 100644 --- a/libs/types/src/tokens.rs +++ b/libs/types/src/tokens.rs @@ -187,8 +187,8 @@ where )] #[cfg_attr(feature = "std", derive(Serialize, Deserialize))] pub struct TrancheCurrency { - pub(crate) pool_id: PoolId, - pub(crate) tranche_id: TrancheId, + pub pool_id: PoolId, + pub tranche_id: TrancheId, } impl From for CurrencyId { diff --git a/pallets/investments/src/lib.rs b/pallets/investments/src/lib.rs index ca4ef743c9..c25a523152 100644 --- a/pallets/investments/src/lib.rs +++ b/pallets/investments/src/lib.rs @@ -224,7 +224,7 @@ pub mod pallet { StorageMap<_, Blake2_128Concat, T::InvestmentId, OrderId, ValueQuery>; #[pallet::storage] - pub(crate) type InvestOrders = StorageDoubleMap< + pub type InvestOrders = StorageDoubleMap< _, Blake2_128Concat, T::AccountId, @@ -234,7 +234,7 @@ pub mod pallet { >; #[pallet::storage] - pub(crate) type RedeemOrders = StorageDoubleMap< + pub type RedeemOrders = StorageDoubleMap< _, Blake2_128Concat, T::AccountId, @@ -245,12 +245,12 @@ pub mod pallet { #[pallet::storage] #[pallet::getter(fn acc_active_invest_order)] - pub(crate) type ActiveInvestOrders = + pub type ActiveInvestOrders = StorageMap<_, Blake2_128Concat, T::InvestmentId, TotalOrder, ValueQuery>; #[pallet::storage] #[pallet::getter(fn acc_active_redeem_order)] - pub(crate) type ActiveRedeemOrders = + pub type ActiveRedeemOrders = StorageMap<_, Blake2_128Concat, T::InvestmentId, TotalOrder, ValueQuery>; #[pallet::storage] diff --git a/runtime/centrifuge/src/migrations.rs b/runtime/centrifuge/src/migrations.rs index c3c3631ff7..0ed0b6d2d1 100644 --- a/runtime/centrifuge/src/migrations.rs +++ b/runtime/centrifuge/src/migrations.rs @@ -9,5 +9,123 @@ // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. +use crate::{Runtime, Weight}; -pub type UpgradeCentrifuge1021 = (); +pub type UpgradeCentrifuge1021 = anemoy_pool::Migration; + +/// Migrate the Anemoy Pool's currency from LpEthUSC to Circle's USDC, +/// native on Polkadot's AssetHub. +mod anemoy_pool { + use cfg_primitives::PoolId; + use cfg_traits::PoolInspect; + use cfg_types::tokens::CurrencyId; + #[cfg(feature = "try-runtime")] + use codec::{Decode, Encode}; + #[cfg(feature = "try-runtime")] + use frame_support::ensure; + use frame_support::traits::{fungibles::Inspect, OnRuntimeUpgrade}; + #[cfg(feature = "try-runtime")] + use pallet_pool_system::PoolDetailsOf; + use sp_std::vec; + #[cfg(feature = "try-runtime")] + use sp_std::vec::Vec; + + use super::*; + use crate::PoolSystem; + + const ANEMOY_POOL_ID: PoolId = 4_139_607_887; + const LP_ETH_USDC: CurrencyId = CurrencyId::ForeignAsset(100_001); + const DOT_NATIVE_USDC: CurrencyId = CurrencyId::ForeignAsset(6); + + pub struct Migration; + + impl OnRuntimeUpgrade for Migration { + #[cfg(feature = "try-runtime")] + fn pre_upgrade() -> Result, &'static str> { + let pool_details: PoolDetailsOf = + PoolSystem::pool(ANEMOY_POOL_ID).ok_or("Could not find Anemoy Pool")?; + + ensure!( + pool_details.currency == LP_ETH_USDC, + "anemoy_pool::Migration: pre_upgrade failing as Anemoy's currency should be LpEthUSDC" + ); + + Ok(pool_details.encode()) + } + + fn on_runtime_upgrade() -> Weight { + // To be executed at 1021, reject higher spec_versions + if crate::VERSION.spec_version >= 1022 { + log::error!( + "anemoy_pool::Migration: NOT execution since VERSION.spec_version >= 1022" + ); + return Weight::zero(); + } + + let (sanity_checks, weight) = verify_sanity_checks(); + if !sanity_checks { + log::error!("anemoy_pool::Migration: Sanity checks FAILED"); + return weight; + } + + pallet_pool_system::Pool::::mutate(ANEMOY_POOL_ID, |details| { + let details = details.as_mut().unwrap(); + details.currency = DOT_NATIVE_USDC; + log::info!("anemoy_pool::Migration: currency set to USDC ✓"); + }); + + weight.saturating_add( + ::DbWeight::get().reads_writes(1, 1), + ) + } + + #[cfg(feature = "try-runtime")] + fn post_upgrade(old_state: Vec) -> Result<(), &'static str> { + let mut old_pool_details = PoolDetailsOf::::decode(&mut old_state.as_ref()) + .map_err(|_| "Error decoding pre-upgrade state")?; + + let pool_details: PoolDetailsOf = + PoolSystem::pool(ANEMOY_POOL_ID).ok_or("Could not find Anemoy Pool")?; + + // Ensure the currency set to USDC is the only mutation performed + old_pool_details.currency = DOT_NATIVE_USDC; + ensure!( + old_pool_details == pool_details, + "Corrupted migration: Only the currency of the Anemoy pool should have changed" + ); + + log::info!("anemoy_pool::Migration: post_upgrade succeeded ✓"); + Ok(()) + } + } + + fn verify_sanity_checks() -> (bool, Weight) { + let res = + crate::Tokens::balance( + LP_ETH_USDC, + &>::account_for(ANEMOY_POOL_ID), + ) == 0 && pallet_investments::ActiveInvestOrders::::iter_keys() + .filter(|investment| investment.pool_id == ANEMOY_POOL_ID) + .count() == 0 && pallet_investments::ActiveRedeemOrders::::iter_keys() + .filter(|investment| investment.pool_id == ANEMOY_POOL_ID) + .count() == 0 && pallet_investments::InvestOrders::::iter_keys() + .filter(|(_, investment)| investment.pool_id == ANEMOY_POOL_ID) + .count() == 0 && pallet_investments::RedeemOrders::::iter_keys() + .filter(|(_, investment)| investment.pool_id == ANEMOY_POOL_ID) + .count() == 0; + + let weight = ::DbWeight::get().reads( + vec![ + 1, // pool account balance read + pallet_investments::ActiveInvestOrders::::iter_keys().count(), + pallet_investments::ActiveRedeemOrders::::iter_keys().count(), + pallet_investments::InvestOrders::::iter_keys().count(), + pallet_investments::RedeemOrders::::iter_keys().count(), + ] + .iter() + .fold(0u64, |acc, x| acc.saturating_add(*x as u64)), + ); + + (res, weight) + } +}