Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

centrifuge: Anemoy pool currency migration #1566

Merged
merged 11 commits into from
Sep 25, 2023
4 changes: 2 additions & 2 deletions libs/types/src/tokens.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

any objections to open these fields visibility? by having them pub(crate) I would have to import he TrancheCurrencyT trait to call generate to build an instance of this type which is quite an overkill imo. let me know if I am not overseeing any requirement 👍

pub tranche_id: TrancheId,
}

impl From<TrancheCurrency> for CurrencyId {
Expand Down
6 changes: 3 additions & 3 deletions pallets/investments/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -224,7 +224,7 @@ pub mod pallet {
StorageMap<_, Blake2_128Concat, T::InvestmentId, OrderId, ValueQuery>;

#[pallet::storage]
pub(crate) type InvestOrders<T: Config> = StorageDoubleMap<
pub type InvestOrders<T: Config> = StorageDoubleMap<
NunoAlexandre marked this conversation as resolved.
Show resolved Hide resolved
_,
Blake2_128Concat,
T::AccountId,
Expand All @@ -234,7 +234,7 @@ pub mod pallet {
>;

#[pallet::storage]
pub(crate) type RedeemOrders<T: Config> = StorageDoubleMap<
pub type RedeemOrders<T: Config> = StorageDoubleMap<
_,
Blake2_128Concat,
T::AccountId,
Expand All @@ -245,7 +245,7 @@ pub mod pallet {

#[pallet::storage]
#[pallet::getter(fn acc_active_invest_order)]
pub(crate) type ActiveInvestOrders<T: Config> =
pub type ActiveInvestOrders<T: Config> =
StorageMap<_, Blake2_128Concat, T::InvestmentId, TotalOrder<T::Amount>, ValueQuery>;

#[pallet::storage]
Expand Down
123 changes: 122 additions & 1 deletion runtime/centrifuge/src/migrations.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,5 +9,126 @@
// 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_types::tokens::CurrencyId;
#[cfg(feature = "try-runtime")]
use codec::{Decode, Encode};
#[cfg(feature = "try-runtime")]
use frame_support::ensure;
use frame_support::traits::OnRuntimeUpgrade;
#[cfg(feature = "try-runtime")]
use pallet_pool_system::PoolDetailsOf;
#[cfg(feature = "try-runtime")]
use sp_std::vec::Vec;

use super::*;
#[cfg(feature = "try-runtime")]
use crate::PoolSystem;

const ANEMOY_POOL_ID: PoolId = 4_139_607_887;
#[cfg(feature = "try-runtime")]
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<Vec<u8>, &'static str> {
let pool_details: PoolDetailsOf<Runtime> =
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::<Runtime>::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(
<Runtime as frame_system::Config>::DbWeight::get().reads(
pallet_pool_system::Pool::<Runtime>::iter_keys()
.count()
.saturating_mul(2) as u64,
),
)
NunoAlexandre marked this conversation as resolved.
Show resolved Hide resolved
}

#[cfg(feature = "try-runtime")]
fn post_upgrade(old_state: Vec<u8>) -> Result<(), &'static str> {
let mut old_pool_details = PoolDetailsOf::<Runtime>::decode(&mut old_state.as_ref())
.map_err(|_| "Error decoding pre-upgrade state")?;

let pool_details: PoolDetailsOf<Runtime> =
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 =
pallet_investments::ActiveInvestOrders::<Runtime>::iter_keys()
.filter(|investment| investment.pool_id == ANEMOY_POOL_ID)
.count() == 0 && pallet_investments::ActiveInvestOrders::<Runtime>::iter_keys()
.filter(|investment| investment.pool_id == ANEMOY_POOL_ID)
.count() == 0 && pallet_investments::InvestOrders::<Runtime>::iter_keys()
.filter(|(_, investment)| investment.pool_id == ANEMOY_POOL_ID)
.count() == 0 && pallet_investments::RedeemOrders::<Runtime>::iter_keys()
.filter(|(_, investment)| investment.pool_id == ANEMOY_POOL_ID)
.count() == 0;

NunoAlexandre marked this conversation as resolved.
Show resolved Hide resolved
let weight = <Runtime as frame_system::Config>::DbWeight::get().reads(
0u64.saturating_add(
pallet_investments::ActiveInvestOrders::<Runtime>::iter_keys().count() as u64,
)
.saturating_add(
pallet_investments::ActiveInvestOrders::<Runtime>::iter_keys().count() as u64,
)
.saturating_add(pallet_investments::InvestOrders::<Runtime>::iter_keys().count() as u64)
.saturating_add(pallet_investments::RedeemOrders::<Runtime>::iter_keys().count() as u64)
// 2x, first for the sanity checks and now for calculating these weights
.saturating_mul(2),
);

(res, weight)
}
}
Loading