From 9e239afc0989746dfc286c14b95af1a0de337084 Mon Sep 17 00:00:00 2001 From: Igor Papandinas <26460174+ipapandinas@users.noreply.github.com> Date: Fri, 9 Aug 2024 11:11:19 +0200 Subject: [PATCH] sanity check: double check threshold variations --- Cargo.lock | 36 ++++--- pallets/dapp-staking-v3/src/migration.rs | 119 ++++++++++++++++++----- runtime/astar/src/lib.rs | 8 +- runtime/shibuya/src/lib.rs | 8 +- runtime/shiden/src/lib.rs | 8 +- 5 files changed, 132 insertions(+), 47 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index ba671faf5..7bb30965c 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1900,7 +1900,7 @@ dependencies = [ [[package]] name = "common" version = "0.1.0" -source = "git+https://github.com/w3f/ring-proof#665f5f51af5734c7b6d90b985dd6861d4c5b4752" +source = "git+https://github.com/w3f/ring-proof#b273d33f9981e2bb3375ab45faeb537f7ee35224" dependencies = [ "ark-ec", "ark-ff", @@ -6681,9 +6681,9 @@ dependencies = [ [[package]] name = "log" -version = "0.4.22" +version = "0.4.21" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a7a70ba024b9dc04c27ea2f0c0548feb474ec5c54bba33a7f72f873a39d07b24" +checksum = "90ed8c1e510134f979dbc4f070f87d4313098b704861a105fe34231c70a3901c" [[package]] name = "lru" @@ -12264,14 +12264,13 @@ dependencies = [ [[package]] name = "ring" version = "0.1.0" -source = "git+https://github.com/w3f/ring-proof#665f5f51af5734c7b6d90b985dd6861d4c5b4752" +source = "git+https://github.com/w3f/ring-proof#b273d33f9981e2bb3375ab45faeb537f7ee35224" dependencies = [ "ark-ec", "ark-ff", "ark-poly", "ark-serialize", "ark-std", - "arrayvec 0.7.4", "blake2 0.10.6", "common", "fflonk", @@ -14266,9 +14265,9 @@ checksum = "cd0b0ec5f1c1ca621c432a25813d8d60c88abe6d3e08a3eb9cf37d97a0fe3d73" [[package]] name = "serde" -version = "1.0.204" +version = "1.0.203" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bc76f558e0cbb2a839d37354c575f1dc3fdc6546b5be373ba43d95f231bf7c12" +checksum = "7253ab4de971e72fb7be983802300c30b5a7f0c2e56fab8abfc6a214307c0094" dependencies = [ "serde_derive", ] @@ -14284,9 +14283,9 @@ dependencies = [ [[package]] name = "serde_derive" -version = "1.0.204" +version = "1.0.203" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e0cd7e117be63d3c3678776753929474f3b04a43a080c744d6b0ae2a8c28e222" +checksum = "500cbc0ebeb6f46627f50f3f5811ccf6bf00643be300b4c3eabc0ef55dc5b5ba" dependencies = [ "proc-macro2", "quote", @@ -15248,7 +15247,7 @@ dependencies = [ [[package]] name = "sp-crypto-ec-utils" version = "0.10.0" -source = "git+https://github.com/paritytech/polkadot-sdk#776e95748901b50ff2833a7d27ea83fd91fbf9d1" +source = "git+https://github.com/paritytech/polkadot-sdk#5fb4c40a3ea24ae3ab2bdfefb3f3a40badc2a583" dependencies = [ "ark-bls12-377", "ark-bls12-377-ext", @@ -15310,7 +15309,7 @@ dependencies = [ [[package]] name = "sp-debug-derive" version = "14.0.0" -source = "git+https://github.com/paritytech/polkadot-sdk#776e95748901b50ff2833a7d27ea83fd91fbf9d1" +source = "git+https://github.com/paritytech/polkadot-sdk#5fb4c40a3ea24ae3ab2bdfefb3f3a40badc2a583" dependencies = [ "proc-macro2", "quote", @@ -15330,7 +15329,7 @@ dependencies = [ [[package]] name = "sp-externalities" version = "0.25.0" -source = "git+https://github.com/paritytech/polkadot-sdk#776e95748901b50ff2833a7d27ea83fd91fbf9d1" +source = "git+https://github.com/paritytech/polkadot-sdk#5fb4c40a3ea24ae3ab2bdfefb3f3a40badc2a583" dependencies = [ "environmental", "parity-scale-codec", @@ -15545,7 +15544,7 @@ dependencies = [ [[package]] name = "sp-runtime-interface" version = "24.0.0" -source = "git+https://github.com/paritytech/polkadot-sdk#776e95748901b50ff2833a7d27ea83fd91fbf9d1" +source = "git+https://github.com/paritytech/polkadot-sdk#5fb4c40a3ea24ae3ab2bdfefb3f3a40badc2a583" dependencies = [ "bytes", "impl-trait-for-tuples", @@ -15577,7 +15576,7 @@ dependencies = [ [[package]] name = "sp-runtime-interface-proc-macro" version = "17.0.0" -source = "git+https://github.com/paritytech/polkadot-sdk#776e95748901b50ff2833a7d27ea83fd91fbf9d1" +source = "git+https://github.com/paritytech/polkadot-sdk#5fb4c40a3ea24ae3ab2bdfefb3f3a40badc2a583" dependencies = [ "Inflector", "expander 2.1.0", @@ -15666,7 +15665,7 @@ source = "git+https://github.com/paritytech/polkadot-sdk?branch=release-polkadot [[package]] name = "sp-std" version = "14.0.0" -source = "git+https://github.com/paritytech/polkadot-sdk#776e95748901b50ff2833a7d27ea83fd91fbf9d1" +source = "git+https://github.com/paritytech/polkadot-sdk#5fb4c40a3ea24ae3ab2bdfefb3f3a40badc2a583" [[package]] name = "sp-storage" @@ -15683,7 +15682,7 @@ dependencies = [ [[package]] name = "sp-storage" version = "19.0.0" -source = "git+https://github.com/paritytech/polkadot-sdk#776e95748901b50ff2833a7d27ea83fd91fbf9d1" +source = "git+https://github.com/paritytech/polkadot-sdk#5fb4c40a3ea24ae3ab2bdfefb3f3a40badc2a583" dependencies = [ "impl-serde", "parity-scale-codec", @@ -15718,7 +15717,7 @@ dependencies = [ [[package]] name = "sp-tracing" version = "16.0.0" -source = "git+https://github.com/paritytech/polkadot-sdk#776e95748901b50ff2833a7d27ea83fd91fbf9d1" +source = "git+https://github.com/paritytech/polkadot-sdk#5fb4c40a3ea24ae3ab2bdfefb3f3a40badc2a583" dependencies = [ "parity-scale-codec", "tracing", @@ -15815,7 +15814,7 @@ dependencies = [ [[package]] name = "sp-wasm-interface" version = "20.0.0" -source = "git+https://github.com/paritytech/polkadot-sdk#776e95748901b50ff2833a7d27ea83fd91fbf9d1" +source = "git+https://github.com/paritytech/polkadot-sdk#5fb4c40a3ea24ae3ab2bdfefb3f3a40badc2a583" dependencies = [ "impl-trait-for-tuples", "log", @@ -16769,7 +16768,6 @@ dependencies = [ "sharded-slab", "smallvec", "thread_local", - "time", "tracing", "tracing-core", "tracing-log 0.2.0", diff --git a/pallets/dapp-staking-v3/src/migration.rs b/pallets/dapp-staking-v3/src/migration.rs index bf741ea18..07075800b 100644 --- a/pallets/dapp-staking-v3/src/migration.rs +++ b/pallets/dapp-staking-v3/src/migration.rs @@ -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 = frame_support::migrations::VersionedMigration< - 7, - 8, - v8::VersionMigrateV7ToV8, - Pallet, - ::DbWeight, - >; + pub type V7ToV8 = + frame_support::migrations::VersionedMigration< + 7, + 8, + v8::VersionMigrateV7ToV8, + Pallet, + ::DbWeight, + >; } // TierThreshold as percentage of the total issuance @@ -56,10 +57,16 @@ mod v8 { use crate::migration::v7::TierParameters as TierParametersV7; use crate::migration::v7::TiersConfiguration as TiersConfigurationV7; - pub struct VersionMigrateV7ToV8(PhantomData<(T, TierThresholds)>); + pub struct VersionMigrateV7ToV8( + PhantomData<(T, TierThresholds, ThresholdVariationPercentage)>, + ); - impl> UncheckedOnRuntimeUpgrade - for VersionMigrateV7ToV8 + impl< + T: Config, + TierThresholds: Get<[TierThreshold; 4]>, + ThresholdVariationPercentage: Get, + > UncheckedOnRuntimeUpgrade + for VersionMigrateV7ToV8 { fn on_runtime_upgrade() -> Weight { // 1. Update static tier parameters with new thresholds from the runtime configurable param TierThresholds @@ -148,51 +155,103 @@ mod v8 { #[cfg(feature = "try-runtime")] fn pre_upgrade() -> Result, TryRuntimeError> { + let tier_thresholds: Result, _> = + BoundedVec::try_from(TierThresholds::get().to_vec()); + assert!(tier_thresholds.is_ok()); + let old_config = v7::TierConfig::::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) -> 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) = + 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::::get(); + assert!(actual_config.is_valid()); + + ensure!( + Pallet::::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::::get(); assert!(actual_tier_params.is_valid()); - let expected_tier_thresholds: BoundedVec = - 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::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, _> = + old_tier_thresholds + .iter() + .map(|t| t.threshold()) + .collect::>() + .try_into(); ensure!( - Pallet::::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::*; @@ -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> { diff --git a/runtime/astar/src/lib.rs b/runtime/astar/src/lib.rs index 511211b00..e27ac7ca5 100644 --- a/runtime/astar/src/lib.rs +++ b/runtime/astar/src/lib.rs @@ -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 { @@ -1306,7 +1308,11 @@ pub type Migrations = ( // permanent migration, do not remove pallet_xcm::migration::MigrateToLatestXcmVersion, // dapp-staking dyn tier threshold migrations - pallet_dapp_staking_v3::migration::versioned_migrations::V7ToV8, + pallet_dapp_staking_v3::migration::versioned_migrations::V7ToV8< + Runtime, + TierThresholds, + ThresholdVariationPercentage, + >, frame_support::migrations::RemovePallet< DmpQueuePalletName, ::DbWeight, diff --git a/runtime/shibuya/src/lib.rs b/runtime/shibuya/src/lib.rs index 218d5a3ec..6e18b7379 100644 --- a/runtime/shibuya/src/lib.rs +++ b/runtime/shibuya/src/lib.rs @@ -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 { @@ -1647,7 +1649,11 @@ pub type Migrations = ( // permanent migration, do not remove pallet_xcm::migration::MigrateToLatestXcmVersion, // dapp-staking dyn tier threshold migrations - pallet_dapp_staking_v3::migration::versioned_migrations::V7ToV8, + pallet_dapp_staking_v3::migration::versioned_migrations::V7ToV8< + Runtime, + TierThresholds, + ThresholdVariationPercentage, + >, frame_support::migrations::RemovePallet< DmpQueuePalletName, ::DbWeight, diff --git a/runtime/shiden/src/lib.rs b/runtime/shiden/src/lib.rs index eb45eecec..1b17e769a 100644 --- a/runtime/shiden/src/lib.rs +++ b/runtime/shiden/src/lib.rs @@ -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 { @@ -1305,7 +1307,11 @@ parameter_types! { pub type Migrations = ( pallet_xcm::migration::MigrateToLatestXcmVersion, // dapp-staking dyn tier threshold migrations - pallet_dapp_staking_v3::migration::versioned_migrations::V7ToV8, + pallet_dapp_staking_v3::migration::versioned_migrations::V7ToV8< + Runtime, + TierThresholds, + ThresholdVariationPercentage, + >, frame_support::migrations::RemovePallet< DmpQueuePalletName, ::DbWeight,