Skip to content

Commit

Permalink
sanity check: double check threshold variations (#1317)
Browse files Browse the repository at this point in the history
  • Loading branch information
ipapandinas authored Aug 9, 2024
1 parent a58f68b commit 6609050
Show file tree
Hide file tree
Showing 5 changed files with 132 additions and 47 deletions.
36 changes: 17 additions & 19 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

119 changes: 94 additions & 25 deletions pallets/dapp-staking-v3/src/migration.rs
Original file line number Diff line number Diff line change
Expand Up @@ -41,13 +41,14 @@ pub mod versioned_migrations {

/// Migration V7 to V8 wrapped in a [`frame_support::migrations::VersionedMigration`], ensuring
/// the migration is only performed when on-chain version is 7.
pub type V7ToV8<T, TierThresholds> = frame_support::migrations::VersionedMigration<
7,
8,
v8::VersionMigrateV7ToV8<T, TierThresholds>,
Pallet<T>,
<T as frame_system::Config>::DbWeight,
>;
pub type V7ToV8<T, TierThresholds, ThresholdVariationPercentage> =
frame_support::migrations::VersionedMigration<
7,
8,
v8::VersionMigrateV7ToV8<T, TierThresholds, ThresholdVariationPercentage>,
Pallet<T>,
<T as frame_system::Config>::DbWeight,
>;
}

// TierThreshold as percentage of the total issuance
Expand All @@ -56,10 +57,16 @@ mod v8 {
use crate::migration::v7::TierParameters as TierParametersV7;
use crate::migration::v7::TiersConfiguration as TiersConfigurationV7;

pub struct VersionMigrateV7ToV8<T, TierThresholds>(PhantomData<(T, TierThresholds)>);
pub struct VersionMigrateV7ToV8<T, TierThresholds, ThresholdVariationPercentage>(
PhantomData<(T, TierThresholds, ThresholdVariationPercentage)>,
);

impl<T: Config, TierThresholds: Get<[TierThreshold; 4]>> UncheckedOnRuntimeUpgrade
for VersionMigrateV7ToV8<T, TierThresholds>
impl<
T: Config,
TierThresholds: Get<[TierThreshold; 4]>,
ThresholdVariationPercentage: Get<u32>,
> UncheckedOnRuntimeUpgrade
for VersionMigrateV7ToV8<T, TierThresholds, ThresholdVariationPercentage>
{
fn on_runtime_upgrade() -> Weight {
// 1. Update static tier parameters with new thresholds from the runtime configurable param TierThresholds
Expand Down Expand Up @@ -148,51 +155,103 @@ mod v8 {

#[cfg(feature = "try-runtime")]
fn pre_upgrade() -> Result<Vec<u8>, TryRuntimeError> {
let tier_thresholds: Result<BoundedVec<TierThreshold, T::NumberOfTiers>, _> =
BoundedVec::try_from(TierThresholds::get().to_vec());
assert!(tier_thresholds.is_ok());

let old_config = v7::TierConfig::<T>::get().ok_or_else(|| {
TryRuntimeError::Other(
"dapp-staking-v3::migration::v8: No old configuration found for TierConfig",
)
})?;
Ok(old_config.number_of_slots.encode())
Ok((old_config.number_of_slots, old_config.tier_thresholds).encode())
}

#[cfg(feature = "try-runtime")]
fn post_upgrade(data: Vec<u8>) -> Result<(), TryRuntimeError> {
let old_number_of_slots = u16::decode(&mut &data[..]).map_err(|_| {
TryRuntimeError::Other("dapp-staking-v3::migration::v8: Failed to decode old value for number of slots")
let (old_number_of_slots, old_tier_thresholds): (u16, BoundedVec<v7::TierThreshold, T::NumberOfTiers>) =
Decode::decode(&mut &data[..]).map_err(|_| {
TryRuntimeError::Other("dapp-staking-v3::migration::v8: Failed to decode old v7 version of tier config")
})?;

// 0. Prerequisites
let actual_config = TierConfig::<T>::get();
assert!(actual_config.is_valid());

ensure!(
Pallet::<T>::on_chain_storage_version() >= 8,
"dapp-staking-v3::migration::v8: Wrong storage version."
);

// Calculated based on "slots_per_tier", which might have slight variations due to the nature of saturating permill distribution.
// 1. Ensure the number of slots is preserved
let actual_number_of_slots = actual_config.total_number_of_slots();
let within_tolerance = (old_number_of_slots - 1)..=old_number_of_slots;
let within_tolerance =
(old_number_of_slots.saturating_sub(1))..=old_number_of_slots.saturating_add(1);

assert!(
within_tolerance.contains(&actual_number_of_slots),
"dapp-staking-v3::migration::v8: New TiersConfiguration format not set correctly, number of slots has derived. Old: {}. Actual: {}.",
"dapp-staking-v3::migration::v8: New TiersConfiguration format not set correctly, number of slots has diverged. Old: {}. Actual: {}.",
old_number_of_slots,
actual_number_of_slots
);

assert!(actual_config.is_valid());

// 2. Ensure the provided static tier params are applied
let actual_tier_params = StaticTierParams::<T>::get();
assert!(actual_tier_params.is_valid());

let expected_tier_thresholds: BoundedVec<TierThreshold, T::NumberOfTiers> =
BoundedVec::try_from(TierThresholds::get().to_vec()).unwrap();
let actual_tier_thresholds = actual_tier_params.tier_thresholds;
assert_eq!(expected_tier_thresholds, actual_tier_thresholds);
let expected_tier_thresholds: Result<BoundedVec<TierThreshold, T::NumberOfTiers>, _> =
BoundedVec::try_from(TierThresholds::get().to_vec());
ensure!(
expected_tier_thresholds.is_ok(),
"dapp-staking-v3::migration::v8: Failed to convert expected tier thresholds."
);
let actual_tier_thresholds = actual_tier_params.clone().tier_thresholds;
assert_eq!(expected_tier_thresholds.unwrap(), actual_tier_thresholds);

// 3. Double check new threshold amounts allowing
let variation_percentage = ThresholdVariationPercentage::get();
let total_issuance = T::Currency::total_issuance();
let average_price = T::NativePriceProvider::average_price();

let old_threshold_amounts: Result<BoundedVec<Balance, T::NumberOfTiers>, _> =
old_tier_thresholds
.iter()
.map(|t| t.threshold())
.collect::<Vec<Balance>>()
.try_into();

ensure!(
Pallet::<T>::on_chain_storage_version() >= 8,
"dapp-staking-v3::migration::v8: Wrong storage version."
old_threshold_amounts.is_ok(),
"dapp-staking-v3::migration::v8: Failed to convert old v7 version tier thresholds to balance amounts."
);
let old_threshold_amounts = old_threshold_amounts.unwrap();
let expected_new_threshold_amounts = actual_config
.calculate_new(&actual_tier_params, average_price, total_issuance)
.tier_thresholds;

for (old_amount, actual_amount) in old_threshold_amounts
.iter()
.zip(expected_new_threshold_amounts)
{
let lower_bound = old_amount
.saturating_mul(100u32.saturating_sub(variation_percentage).into())
.saturating_div(100u32.into());
let upper_bound = old_amount
.saturating_mul(100u32.saturating_add(variation_percentage).into())
.saturating_div(100u32.into());

assert!(
(lower_bound..=upper_bound).contains(&actual_amount),
"dapp-staking-v3::migration::v8: New tier threshold amounts diverged to much from old values, consider adjusting static tier parameters. Old: {}. Actual: {}.",
old_amount,
actual_amount
);
}

Ok(())
}
}
}

/// Translate DAppTiers to include rank rewards.
mod v7 {
use super::*;
Expand All @@ -211,6 +270,16 @@ mod v7 {
},
}

impl TierThreshold {
/// Return threshold for the tier.
pub fn threshold(&self) -> Balance {
match self {
Self::FixedTvlAmount { amount } => *amount,
Self::DynamicTvlAmount { amount, .. } => *amount,
}
}
}

/// Top level description of tier slot parameters used to calculate tier configuration.
#[derive(Encode, Decode)]
pub struct TierParameters<NT: Get<u32>> {
Expand Down
8 changes: 7 additions & 1 deletion runtime/astar/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1275,6 +1275,8 @@ pub type Executive = frame_executive::Executive<
>;

parameter_types! {
// Threshold amount variation allowed for this migration - 10%
pub const ThresholdVariationPercentage: u32 = 10;
// percentages below are calulated based on total issuance at the time when dApp staking v3 was launched (8.4B)
pub const TierThresholds: [TierThreshold; 4] = [
TierThreshold::DynamicPercentage {
Expand Down Expand Up @@ -1306,7 +1308,11 @@ pub type Migrations = (
// permanent migration, do not remove
pallet_xcm::migration::MigrateToLatestXcmVersion<Runtime>,
// dapp-staking dyn tier threshold migrations
pallet_dapp_staking_v3::migration::versioned_migrations::V7ToV8<Runtime, TierThresholds>,
pallet_dapp_staking_v3::migration::versioned_migrations::V7ToV8<
Runtime,
TierThresholds,
ThresholdVariationPercentage,
>,
frame_support::migrations::RemovePallet<
DmpQueuePalletName,
<Runtime as frame_system::Config>::DbWeight,
Expand Down
8 changes: 7 additions & 1 deletion runtime/shibuya/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1616,6 +1616,8 @@ pub type Executive = frame_executive::Executive<
>;

parameter_types! {
// Threshold amount variation allowed for this migration - 150%
pub const ThresholdVariationPercentage: u32 = 150;
// percentages below are calulated based on a total issuance at the time when dApp staking v3 was launched (147M)
pub const TierThresholds: [TierThreshold; 4] = [
TierThreshold::DynamicPercentage {
Expand Down Expand Up @@ -1647,7 +1649,11 @@ pub type Migrations = (
// permanent migration, do not remove
pallet_xcm::migration::MigrateToLatestXcmVersion<Runtime>,
// dapp-staking dyn tier threshold migrations
pallet_dapp_staking_v3::migration::versioned_migrations::V7ToV8<Runtime, TierThresholds>,
pallet_dapp_staking_v3::migration::versioned_migrations::V7ToV8<
Runtime,
TierThresholds,
ThresholdVariationPercentage,
>,
frame_support::migrations::RemovePallet<
DmpQueuePalletName,
<Runtime as frame_system::Config>::DbWeight,
Expand Down
8 changes: 7 additions & 1 deletion runtime/shiden/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1275,6 +1275,8 @@ pub type Executive = frame_executive::Executive<
>;

parameter_types! {
// Threshold amount variation allowed for this migration - 10%
pub const ThresholdVariationPercentage: u32 = 10;
// percentages below are calulated based on a total issuance at the time when dApp staking v3 was launched (84.3M)
pub const TierThresholds: [TierThreshold; 4] = [
TierThreshold::DynamicPercentage {
Expand Down Expand Up @@ -1305,7 +1307,11 @@ parameter_types! {
pub type Migrations = (
pallet_xcm::migration::MigrateToLatestXcmVersion<Runtime>,
// dapp-staking dyn tier threshold migrations
pallet_dapp_staking_v3::migration::versioned_migrations::V7ToV8<Runtime, TierThresholds>,
pallet_dapp_staking_v3::migration::versioned_migrations::V7ToV8<
Runtime,
TierThresholds,
ThresholdVariationPercentage,
>,
frame_support::migrations::RemovePallet<
DmpQueuePalletName,
<Runtime as frame_system::Config>::DbWeight,
Expand Down

0 comments on commit 6609050

Please sign in to comment.