diff --git a/Cargo.lock b/Cargo.lock index 174f8ac44..29eb47045 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -955,7 +955,6 @@ dependencies = [ "impl-trait-for-tuples", "log", "once_cell", - "orml-oracle", "orml-traits", "pallet-assets", "pallet-collective", @@ -1011,7 +1010,6 @@ dependencies = [ "moonbeam-rpc-primitives-debug", "moonbeam-rpc-primitives-txpool", "num_enum 0.5.11", - "orml-oracle", "orml-xcm-support", "orml-xtokens", "pallet-assets", @@ -1048,7 +1046,6 @@ dependencies = [ "pallet-migrations", "pallet-multisig", "pallet-preimage", - "pallet-price-aggregator", "pallet-proxy", "pallet-safe-mode", "pallet-scheduler", @@ -6686,7 +6683,6 @@ dependencies = [ "hex", "libsecp256k1", "moonbeam-rpc-primitives-debug", - "orml-oracle", "pallet-assets", "pallet-aura", "pallet-balances", @@ -6704,7 +6700,6 @@ dependencies = [ "pallet-evm-precompile-dispatch", "pallet-inflation", "pallet-membership", - "pallet-price-aggregator", "pallet-proxy", "pallet-safe-mode", "pallet-session", @@ -9040,25 +9035,6 @@ dependencies = [ "syn 1.0.109", ] -[[package]] -name = "orml-oracle" -version = "1.4.0" -source = "git+https://github.com/AstarNetwork/open-runtime-module-library?branch=stable2506#b167585299589570f01ef40dcd68361f5c6cbaa1" -dependencies = [ - "frame-benchmarking", - "frame-support", - "frame-system", - "orml-traits", - "orml-utilities", - "parity-scale-codec", - "scale-info", - "serde", - "sp-application-crypto", - "sp-io", - "sp-runtime", - "sp-std", -] - [[package]] name = "orml-traits" version = "1.4.0" @@ -10407,28 +10383,6 @@ dependencies = [ "sp-runtime", ] -[[package]] -name = "pallet-price-aggregator" -version = "0.1.0" -dependencies = [ - "astar-primitives", - "frame-benchmarking", - "frame-support", - "frame-system", - "log", - "num-traits", - "orml-traits", - "pallet-balances", - "parity-scale-codec", - "scale-info", - "serde", - "sp-arithmetic", - "sp-core", - "sp-io", - "sp-runtime", - "sp-std", -] - [[package]] name = "pallet-proxy" version = "41.0.0" @@ -10758,26 +10712,6 @@ dependencies = [ "sp-runtime", ] -[[package]] -name = "pallet-static-price-provider" -version = "0.1.0" -dependencies = [ - "astar-primitives", - "frame-benchmarking", - "frame-support", - "frame-system", - "log", - "pallet-balances", - "parity-scale-codec", - "scale-info", - "serde", - "sp-arithmetic", - "sp-core", - "sp-io", - "sp-runtime", - "sp-std", -] - [[package]] name = "pallet-sudo" version = "41.0.0" @@ -15998,7 +15932,6 @@ dependencies = [ "moonbeam-rpc-primitives-debug", "moonbeam-rpc-primitives-txpool", "num_enum 0.5.11", - "orml-oracle", "orml-xcm-support", "orml-xtokens", "pallet-assets", @@ -16040,7 +15973,6 @@ dependencies = [ "pallet-migrations", "pallet-multisig", "pallet-preimage", - "pallet-price-aggregator", "pallet-proxy", "pallet-safe-mode", "pallet-scheduler", @@ -16123,7 +16055,6 @@ dependencies = [ "moonbeam-rpc-primitives-debug", "moonbeam-rpc-primitives-txpool", "num_enum 0.5.11", - "orml-oracle", "orml-xcm-support", "orml-xtokens", "pallet-assets", @@ -16157,7 +16088,6 @@ dependencies = [ "pallet-message-queue", "pallet-migrations", "pallet-multisig", - "pallet-price-aggregator", "pallet-proxy", "pallet-session", "pallet-sudo", diff --git a/Cargo.toml b/Cargo.toml index 8770d03cc..cc4e27b35 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -308,7 +308,6 @@ polkadot-service = { git = "https://github.com/paritytech/polkadot-sdk", branch orml-xtokens = { git = "https://github.com/AstarNetwork/open-runtime-module-library", branch = "stable2506", default-features = false } orml-traits = { git = "https://github.com/AstarNetwork/open-runtime-module-library", branch = "stable2506", default-features = false } orml-xcm-support = { git = "https://github.com/AstarNetwork/open-runtime-module-library", branch = "stable2506", default-features = false } -orml-oracle = { git = "https://github.com/AstarNetwork/open-runtime-module-library", branch = "stable2506", default-features = false } # Astar pallets & modules # (wasm) @@ -320,8 +319,6 @@ pallet-inflation = { path = "./pallets/inflation", default-features = false } pallet-dynamic-evm-base-fee = { path = "./pallets/dynamic-evm-base-fee", default-features = false } pallet-unified-accounts = { path = "./pallets/unified-accounts", default-features = false } astar-xcm-benchmarks = { path = "./pallets/astar-xcm-benchmarks", default-features = false } -pallet-static-price-provider = { path = "./pallets/static-price-provider", default-features = false } -pallet-price-aggregator = { path = "./pallets/price-aggregator", default-features = false } pallet-collective-proxy = { path = "./pallets/collective-proxy", default-features = false } vesting-mbm = { path = "./pallets/vesting-mbm", default-features = false } democracy-mbm = { path = "./pallets/democracy-mbm", default-features = false } diff --git a/pallets/dapp-staking/src/benchmarking/utils.rs b/pallets/dapp-staking/src/benchmarking/utils.rs index 7e04eb3d9..4532b90e0 100644 --- a/pallets/dapp-staking/src/benchmarking/utils.rs +++ b/pallets/dapp-staking/src/benchmarking/utils.rs @@ -19,7 +19,7 @@ use super::{Pallet as DappStaking, *}; use astar_primitives::{ - dapp_staking::{FIXED_NUMBER_OF_TIER_SLOTS, FIXED_TIER_SLOTS_ARGS}, + dapp_staking::FIXED_NUMBER_OF_TIER_SLOTS, Balance, }; @@ -196,7 +196,6 @@ pub(super) fn init_tier_settings() { }, ]) .unwrap(), - slot_number_args: FIXED_TIER_SLOTS_ARGS, tier_rank_multipliers: BoundedVec::try_from(vec![0, 24_000, 46_700, 0]).unwrap(), }; diff --git a/pallets/dapp-staking/src/lib.rs b/pallets/dapp-staking/src/lib.rs index ed4afc534..0cd5ea827 100644 --- a/pallets/dapp-staking/src/lib.rs +++ b/pallets/dapp-staking/src/lib.rs @@ -57,7 +57,6 @@ use astar_primitives::{ dapp_staking::{ AccountCheck, CycleConfiguration, DAppId, EraNumber, Observer as DAppStakingObserver, PeriodNumber, Rank, RankedTier, SmartContractHandle, StakingRewardHandler, TierId, - FIXED_TIER_SLOTS_ARGS, }, Balance, BlockNumber, }; @@ -95,7 +94,7 @@ pub mod pallet { use super::*; /// The current storage version. - pub const STORAGE_VERSION: StorageVersion = StorageVersion::new(11); + pub const STORAGE_VERSION: StorageVersion = StorageVersion::new(12); #[pallet::pallet] #[pallet::storage_version(STORAGE_VERSION)] @@ -167,11 +166,6 @@ pub mod pallet { #[pallet::constant] type MaxNumberOfContracts: Get; - /// Legacy bound for backward compatibility with pre-v11 DAppTierRewards. - // TODO: Can be removed to use MaxNumberOfContracts only after period 4 periods post-revamp-upgrade. - #[pallet::constant] - type MaxNumberOfContractsLegacy: Get; - /// Maximum number of unlocking chunks that can exist per account at a time. #[pallet::constant] type MaxUnlockingChunks: Get; @@ -513,7 +507,6 @@ pub mod pallet { pub reward_portion: Vec, pub slot_distribution: Vec, pub tier_thresholds: Vec, - pub slot_number_args: (u64, u64), pub slots_per_tier: Vec, pub safeguard: Option, pub tier_rank_multipliers: Vec, @@ -551,7 +544,6 @@ pub mod pallet { required_percentage: Perbill::zero(), }, ], - slot_number_args: FIXED_TIER_SLOTS_ARGS, slots_per_tier: vec![100; num_tiers as usize], safeguard: None, tier_rank_multipliers: vec![0u32, 24_000, 46_700, 0], @@ -577,7 +569,6 @@ pub mod pallet { self.tier_thresholds.clone(), ) .expect("Invalid number of tier thresholds provided."), - slot_number_args: self.slot_number_args, tier_rank_multipliers: BoundedVec::::try_from( self.tier_rank_multipliers.clone(), ) @@ -1973,7 +1964,7 @@ pub mod pallet { // Prepare and return tier & rewards info. // In case rewards creation fails, we just write the default value. This should never happen though. ( - DAppTierRewards::::new( + DAppTierRewards::::new( dapp_tiers, tier_rewards, period, diff --git a/pallets/dapp-staking/src/migration.rs b/pallets/dapp-staking/src/migration.rs index 400dcdb34..e2e8241f2 100644 --- a/pallets/dapp-staking/src/migration.rs +++ b/pallets/dapp-staking/src/migration.rs @@ -17,7 +17,6 @@ // along with Astar. If not, see . use super::*; -use astar_primitives::dapp_staking::FIXED_TIER_SLOTS_ARGS; use core::marker::PhantomData; use frame_support::traits::UncheckedOnRuntimeUpgrade; @@ -33,413 +32,155 @@ use try_runtime_imports::*; pub mod versioned_migrations { use super::*; - /// Migration V10 to V11 wrapped in a [`frame_support::migrations::VersionedMigration`], ensuring - /// the migration is only performed when on-chain version is 10. - pub type V10ToV11 = - frame_support::migrations::VersionedMigration< - 10, - 11, - v11::VersionMigrateV10ToV11, - Pallet, - ::DbWeight, - >; + /// Migration V11 to V12: + /// - Prune old `PeriodEnd` entries for periods 0..=6 + /// - Migrate `StaticTierParams` to remove `slot_number_args` and `DynamicPercentage` + pub type V11ToV12 = frame_support::migrations::VersionedMigration< + 11, + 12, + v12::VersionMigrateV11ToV12, + Pallet, + ::DbWeight, + >; } -/// Configuration for V11 tier parameters -pub trait TierParamsV11Config { - fn reward_portion() -> [Permill; 4]; - fn slot_distribution() -> [Permill; 4]; - fn tier_thresholds() -> [TierThreshold; 4]; - fn slot_number_args() -> (u64, u64); - fn tier_rank_multipliers() -> [u32; 4]; -} - -pub struct DefaultTierParamsV11; -impl TierParamsV11Config for DefaultTierParamsV11 { - fn reward_portion() -> [Permill; 4] { - [ - Permill::from_percent(0), - Permill::from_percent(70), - Permill::from_percent(30), - Permill::from_percent(0), - ] - } - - fn slot_distribution() -> [Permill; 4] { - [ - Permill::from_percent(0), - Permill::from_parts(375_000), // 37.5% - Permill::from_parts(625_000), // 62.5% - Permill::from_percent(0), - ] - } +mod v12 { + use super::*; - fn tier_thresholds() -> [TierThreshold; 4] { - [ - TierThreshold::FixedPercentage { - required_percentage: Perbill::from_parts(23_200_000), // 2.32% - }, - TierThreshold::FixedPercentage { - required_percentage: Perbill::from_parts(9_300_000), // 0.93% - }, - TierThreshold::FixedPercentage { - required_percentage: Perbill::from_parts(3_500_000), // 0.35% - }, - // Tier 3: unreachable dummy - TierThreshold::FixedPercentage { - required_percentage: Perbill::from_parts(0), // 0% - }, - ] - } + /// Maximum period number to prune (inclusive). + const PRUNE_MAX_PERIOD: PeriodNumber = 6; - fn slot_number_args() -> (u64, u64) { - FIXED_TIER_SLOTS_ARGS + /// Old `TierThreshold` enum that includes the removed `DynamicPercentage` variant. + #[derive(Encode, Decode, Clone)] + pub enum OldTierThreshold { + FixedPercentage { required_percentage: Perbill }, + DynamicPercentage { + percentage: Perbill, + minimum_required_percentage: Perbill, + maximum_possible_percentage: Perbill, + }, } - fn tier_rank_multipliers() -> [u32; 4] { - [0, 24_000, 46_700, 0] + /// Old `TierParameters` shape (with `slot_number_args` field). + #[derive(Encode, Decode, Clone)] + pub struct OldTierParameters> { + pub reward_portion: BoundedVec, + pub slot_distribution: BoundedVec, + pub tier_thresholds: BoundedVec, + pub slot_number_args: (u64, u64), + pub tier_rank_multipliers: BoundedVec, } -} -mod v11 { - use super::*; + #[frame_support::storage_alias] + pub type OldStaticTierParams = + StorageValue, OldTierParameters<::NumberOfTiers>, OptionQuery>; - pub struct VersionMigrateV10ToV11( - PhantomData<(T, P, OldErasVoting, OldErasBnE)>, - ); + pub struct VersionMigrateV11ToV12(PhantomData); - impl, OldErasBnE: Get> - UncheckedOnRuntimeUpgrade for VersionMigrateV10ToV11 - { + impl UncheckedOnRuntimeUpgrade for VersionMigrateV11ToV12 { fn on_runtime_upgrade() -> Weight { - let old_eras_voting = OldErasVoting::get(); - let old_eras_bne = OldErasBnE::get(); - let mut reads: u64 = 0; let mut writes: u64 = 0; - // 0. Safety: remove excess dApps if count exceeds new limit - let current_integrated_dapps = IntegratedDApps::::count(); - reads += 1; - - let max_dapps_allowed = T::MaxNumberOfContracts::get(); - - if current_integrated_dapps > max_dapps_allowed { - log::warn!( - target: LOG_TARGET, - "Safety net triggered: {} dApps exceed limit of {}. Removing {} excess dApps.", - current_integrated_dapps, - max_dapps_allowed, - current_integrated_dapps - max_dapps_allowed - ); - - let excess = current_integrated_dapps.saturating_sub(max_dapps_allowed); - let victims: Vec<_> = IntegratedDApps::::iter() - .take(excess as usize) - .map(|(contract, dapp_info)| (contract, dapp_info.id)) - .collect(); - - reads += excess as u64; - - for (contract, dapp_id) in victims { - ContractStake::::remove(&dapp_id); - IntegratedDApps::::remove(&contract); - writes += 2; - - let current_era = ActiveProtocolState::::get().era; - Pallet::::deposit_event(Event::::DAppUnregistered { - smart_contract: contract, - era: current_era, - }); + // 1. Prune old PeriodEnd entries for periods 0..=6 + for period in 0..=PRUNE_MAX_PERIOD { + reads += 1; + if PeriodEnd::::take(period).is_some() { + writes += 1; log::info!( target: LOG_TARGET, - "Safety net removed dApp ID {} (contract: {:?})", - dapp_id, - core::any::type_name::() + "Pruned PeriodEnd entry for period {}", + period ); } - - // ActiveProtocolState::get() for era => 1 read (done once for all events) - reads += 1; - } - - // 1. Migrate StaticTierParams - let reward_portion = BoundedVec::::truncate_from( - P::reward_portion().to_vec(), - ); - let slot_distribution = BoundedVec::::truncate_from( - P::slot_distribution().to_vec(), - ); - let tier_thresholds = BoundedVec::::truncate_from( - P::tier_thresholds().to_vec(), - ); - let tier_rank_multipliers = BoundedVec::::truncate_from( - P::tier_rank_multipliers().to_vec(), - ); - - let new_params = TierParameters:: { - reward_portion, - slot_distribution, - tier_thresholds, - slot_number_args: P::slot_number_args(), - tier_rank_multipliers, - }; - - if !new_params.is_valid() { - log::error!( - target: LOG_TARGET, - "New TierParameters validation failed. Enabling maintenance mode." - ); - - // ActiveProtocolState::mutate => 1 read + 1 write - ActiveProtocolState::::mutate(|state| { - state.maintenance = true; - }); - reads += 1; - writes += 1; - - return T::DbWeight::get().reads_writes(reads, writes); } - // StaticTierParams::put => 1 write - StaticTierParams::::put(new_params); - writes += 1; - log::info!(target: LOG_TARGET, "StaticTierParams updated successfully"); - - // 2. Update ActiveProtocolState in a SINGLE mutate (avoid extra .get() read) - // ActiveProtocolState::mutate => 1 read + 1 write - ActiveProtocolState::::mutate(|state| { - if state.period_info.subperiod == Subperiod::Voting { - let current_block: u32 = - frame_system::Pallet::::block_number().saturated_into(); - - // Old/new voting period lengths (in blocks) - let old_voting_length: u32 = - old_eras_voting.saturating_mul(T::CycleConfiguration::blocks_per_era()); - let new_voting_length: u32 = Pallet::::blocks_per_voting_period() - .max(T::CycleConfiguration::blocks_per_era()); - - // Old schedule - let remaining_old: u32 = state.next_era_start.saturating_sub(current_block); - let elapsed: u32 = old_voting_length.saturating_sub(remaining_old); - - // New schedule - let remaining_new: u32 = new_voting_length.saturating_sub(elapsed); - - // If new period has already passed (elapsed >= new_voting_length), - // schedule for next block. Otherwise, use the calculated remainder. - state.next_era_start = if remaining_new == 0 { - current_block.saturating_add(1) - } else { - current_block.saturating_add(remaining_new) - }; - - log::info!( - target: LOG_TARGET, - "ActiveProtocolState updated: next_era_start (old_length={}, new_length={}, elapsed={}, remaining_new={})", - old_voting_length, - new_voting_length, - elapsed, - remaining_new - ); - } - if state.period_info.subperiod == Subperiod::Voting { - // Recalculate next_era_start block - let current_block: u32 = - frame_system::Pallet::::block_number().saturated_into(); - let new_voting_length: u32 = Pallet::::blocks_per_voting_period() - .max(T::CycleConfiguration::blocks_per_era()); - let remaining_old: u32 = state.next_era_start.saturating_sub(current_block); - // Carry over remaining time, but never extend beyond the new voting length. - // If already overdue, schedule for the next block. - let remaining_new: u32 = remaining_old.min(new_voting_length).max(1); + // 2. Migrate StaticTierParams to new shape (remove slot_number_args, convert DynamicPercentage) + reads += 1; + if let Some(old_params) = OldStaticTierParams::::get() { + let new_tier_thresholds: Vec = old_params + .tier_thresholds + .iter() + .map(|t| match t { + OldTierThreshold::FixedPercentage { + required_percentage, + } => TierThreshold::FixedPercentage { + required_percentage: *required_percentage, + }, + OldTierThreshold::DynamicPercentage { percentage, .. } => { + TierThreshold::FixedPercentage { + required_percentage: *percentage, + } + } + }) + .collect(); - state.next_era_start = current_block.saturating_add(remaining_new); + let new_params = TierParameters:: { + reward_portion: old_params.reward_portion, + slot_distribution: old_params.slot_distribution, + tier_thresholds: BoundedVec::truncate_from(new_tier_thresholds), + tier_rank_multipliers: old_params.tier_rank_multipliers, + }; - log::info!( - target: LOG_TARGET, - "ActiveProtocolState updated: next_era_start (remaining_old={}, remaining_new={})", - remaining_old, - remaining_new - ); + if new_params.is_valid() { + StaticTierParams::::put(new_params); + writes += 1; + log::info!(target: LOG_TARGET, "StaticTierParams migrated to v12 successfully"); } else { - // Build&Earn: adjust remainder for next_subperiod_start_era - let new_eras_total: EraNumber = - T::CycleConfiguration::eras_per_build_and_earn_subperiod(); - - // "only the remainder" logic - let current_era: EraNumber = state.era; - let old_end: EraNumber = state.period_info.next_subperiod_start_era; - - let remaining_old: EraNumber = old_end.saturating_sub(current_era); - let elapsed: EraNumber = old_eras_bne.saturating_sub(remaining_old); - - let remaining_new: EraNumber = new_eras_total.saturating_sub(elapsed); - - state.period_info.next_subperiod_start_era = - current_era.saturating_add(remaining_new); - - log::info!( + log::error!( target: LOG_TARGET, - "ActiveProtocolState updated: next_subperiod_start_era (remainder-adjusted)" + "New TierParameters validation failed during v12 migration. Enabling maintenance mode." ); + ActiveProtocolState::::mutate(|state| { + state.maintenance = true; + }); + reads += 1; + writes += 1; } - }); - reads += 1; - writes += 1; + } else { + log::warn!( + target: LOG_TARGET, + "No StaticTierParams found during v12 migration (raw storage empty or decode failed)." + ); + } + + // 3. Clean up raw storage for old StaticTierParams key (same key, already overwritten above) + // No additional action needed since StaticTierParams::put already overwrites. T::DbWeight::get().reads_writes(reads, writes) } #[cfg(feature = "try-runtime")] fn pre_upgrade() -> Result, TryRuntimeError> { - let protocol_state = ActiveProtocolState::::get(); - let current_block: u32 = frame_system::Pallet::::block_number().saturated_into(); - - let pre_dapp_count = IntegratedDApps::::count(); - let max_allowed = T::MaxNumberOfContracts::get(); - - log::info!( - target: LOG_TARGET, - "Pre-upgrade: dApp count={}, max={}, cleanup_needed={}", - pre_dapp_count, - max_allowed, - pre_dapp_count > max_allowed - ); - - Ok(( - protocol_state.period_info.subperiod, - protocol_state.era, - protocol_state.next_era_start, - protocol_state.period_info.next_subperiod_start_era, - current_block, - pre_dapp_count, - max_allowed, - ) - .encode()) + log::info!(target: LOG_TARGET, "V11ToV12 pre-upgrade: checking state"); + Ok(Vec::new()) } #[cfg(feature = "try-runtime")] - fn post_upgrade(data: Vec) -> Result<(), TryRuntimeError> { - let ( - old_subperiod, - old_era, - old_next_era_start, - old_next_subperiod_era, - pre_block, - pre_dapp_count, - max_allowed, - ): (Subperiod, EraNumber, u32, EraNumber, u32, u32, u32) = - Decode::decode(&mut &data[..]) - .map_err(|_| TryRuntimeError::Other("Failed to decode pre-upgrade data"))?; - let old_eras_voting = OldErasVoting::get(); - let old_eras_bne = OldErasBnE::get(); - + fn post_upgrade(_data: Vec) -> Result<(), TryRuntimeError> { // Verify storage version ensure!( - Pallet::::on_chain_storage_version() == StorageVersion::new(11), - "Storage version should be 11" + Pallet::::on_chain_storage_version() == StorageVersion::new(12), + "Storage version should be 12" ); - // 1. Verify cleanup worked - let post_dapp_count = IntegratedDApps::::count(); - log::debug!( - "post_dapp_count={}, max_allowed={}", - post_dapp_count, - max_allowed - ); + // Verify StaticTierParams can be decoded with new type + let params = StaticTierParams::::get(); ensure!( - post_dapp_count <= max_allowed, - "dApp count still exceeds limit", + params.is_valid(), + "StaticTierParams invalid after migration" ); - if pre_dapp_count > max_allowed { - let expected_removed = pre_dapp_count - max_allowed; - let actual_removed = pre_dapp_count - post_dapp_count; - log::debug!( - "Removed {} dApps, expected to remove {}", - actual_removed, - expected_removed - ); + // Verify PeriodEnd entries for periods 0..=6 are removed + for period in 0..=PRUNE_MAX_PERIOD { ensure!( - actual_removed == expected_removed, - "Mismatch in the expected dApps to be unregistered" + PeriodEnd::::get(period).is_none(), + "PeriodEnd entry should be removed for pruned period" ); } - // 2. Verify new StaticTierParams are valid - let new_params = StaticTierParams::::get(); - ensure!(new_params.is_valid(), "New tier params invalid"); - ensure!( - new_params.reward_portion.as_slice() == P::reward_portion(), - "reward_portion mismatch" - ); - ensure!( - new_params.tier_rank_multipliers.as_slice() == P::tier_rank_multipliers(), - "tier_rank_multipliers mismatch" - ); - - // 3. Verify ActiveProtocolState update - let protocol_state = ActiveProtocolState::::get(); - ensure!(!protocol_state.maintenance, "Maintenance mode enabled"); - - if old_subperiod == Subperiod::Voting { - let old_voting_length: u32 = - old_eras_voting.saturating_mul(T::CycleConfiguration::blocks_per_era()); - let new_voting_length: u32 = Pallet::::blocks_per_voting_period(); - - let remaining_old: u32 = old_next_era_start.saturating_sub(pre_block); - let elapsed: u32 = old_voting_length.saturating_sub(remaining_old); - let remaining_new: u32 = new_voting_length.saturating_sub(elapsed); - - let expected = if remaining_new == 0 { - pre_block.saturating_add(1) - } else { - pre_block.saturating_add(remaining_new) - }; - - ensure!( - protocol_state.next_era_start == expected, - "Voting: next_era_start incorrect" - ); - } else { - let new_total: EraNumber = - T::CycleConfiguration::eras_per_build_and_earn_subperiod(); - let remaining_old: EraNumber = old_next_subperiod_era.saturating_sub(old_era); - let elapsed: EraNumber = old_eras_bne.saturating_sub(remaining_old); - let remaining_new: EraNumber = new_total.saturating_sub(elapsed); - let expected: EraNumber = old_era.saturating_add(remaining_new); - - ensure!( - protocol_state.period_info.next_subperiod_start_era == expected, - "BuildEarn: next_subperiod_start_era incorrect" - ); - ensure!( - old_next_era_start > expected, - "next_era_start did not update as expected" - ); - } - - log::info!(target: LOG_TARGET, "Post-upgrade: All checks passed"); + log::info!(target: LOG_TARGET, "V11ToV12 post-upgrade: all checks passed"); Ok(()) } } } - -mod v10 { - use super::*; - use frame_support::storage_alias; - - /// v10 TierParameters (without tier_rank_multipliers) - #[derive(Encode, Decode, Clone)] - pub struct TierParameters> { - pub reward_portion: BoundedVec, - pub slot_distribution: BoundedVec, - pub tier_thresholds: BoundedVec, - pub slot_number_args: (u64, u64), - } - - #[storage_alias] - pub type StaticTierParams = - StorageValue, TierParameters<::NumberOfTiers>, OptionQuery>; -} diff --git a/pallets/dapp-staking/src/test/mock.rs b/pallets/dapp-staking/src/test/mock.rs index ebea016ef..82033f602 100644 --- a/pallets/dapp-staking/src/test/mock.rs +++ b/pallets/dapp-staking/src/test/mock.rs @@ -34,7 +34,7 @@ use sp_runtime::{BuildStorage, Permill}; use sp_std::cell::RefCell; use astar_primitives::{ - dapp_staking::{Observer as DappStakingObserver, SmartContract, FIXED_TIER_SLOTS_ARGS}, + dapp_staking::{Observer as DappStakingObserver, SmartContract}, Balance, BlockNumber, }; use frame_system::{EnsureRoot, EnsureSignedBy}; @@ -207,7 +207,6 @@ impl pallet_dapp_staking::Config for Test { type EraRewardSpanLength = ConstU32<8>; type RewardRetentionInPeriods = ConstU32<2>; type MaxNumberOfContracts = ConstU32<10>; - type MaxNumberOfContractsLegacy = ConstU32<10>; type MaxUnlockingChunks = ConstU32<5>; type MinimumLockedAmount = ConstU128; type UnlockingPeriod = ConstU32<2>; @@ -304,27 +303,20 @@ impl ExtBuilder { ]) .unwrap(), tier_thresholds: BoundedVec::try_from(vec![ - TierThreshold::DynamicPercentage { - percentage: Perbill::from_parts(11_112_000), // 1.1112% - minimum_required_percentage: Perbill::from_parts(8_889_000), // 0.8889% - maximum_possible_percentage: Perbill::from_parts(13_000_000), // 1.3% + TierThreshold::FixedPercentage { + required_percentage: Perbill::from_parts(11_112_000), // 1.1112% }, - TierThreshold::DynamicPercentage { - percentage: Perbill::from_parts(5_556_000), // 0.5556% - minimum_required_percentage: Perbill::from_parts(4_400_000), // 0.44% - maximum_possible_percentage: Perbill::from_percent(100), + TierThreshold::FixedPercentage { + required_percentage: Perbill::from_parts(5_556_000), // 0.5556% }, - TierThreshold::DynamicPercentage { - percentage: Perbill::from_parts(2_223_000), // 0.2223% - minimum_required_percentage: Perbill::from_parts(2_223_000), // 0.2223% - maximum_possible_percentage: Perbill::from_percent(100), + TierThreshold::FixedPercentage { + required_percentage: Perbill::from_parts(2_223_000), // 0.2223% }, TierThreshold::FixedPercentage { required_percentage: Perbill::from_parts(1_667_000), // 0.1667% }, ]) .unwrap(), - slot_number_args: FIXED_TIER_SLOTS_ARGS, tier_rank_multipliers: BoundedVec::try_from(vec![0, 24_000, 46_700, 0]).unwrap(), }; diff --git a/pallets/dapp-staking/src/test/tests.rs b/pallets/dapp-staking/src/test/tests.rs index fd4307316..6d1bb8266 100644 --- a/pallets/dapp-staking/src/test/tests.rs +++ b/pallets/dapp-staking/src/test/tests.rs @@ -3409,10 +3409,7 @@ fn base_number_of_slots_is_respected() { "Number of slots must respect the fixed slot limit." ); - // Mutate slot_number_args and ensure full tier config recalculation remains unchanged. - StaticTierParams::::mutate(|params| { - params.slot_number_args = (123, 456); - }); + // Force another era and verify config stays the same. assert_ok!(DappStaking::force(RuntimeOrigin::root(), ForcingType::Era)); run_for_blocks(1); @@ -3420,11 +3417,11 @@ fn base_number_of_slots_is_respected() { assert_eq!( config_after.total_number_of_slots(), FIXED_NUMBER_OF_TIER_SLOTS, - "Number of slots must remain fixed regardless of slot_number_args." + "Number of slots must remain fixed." ); assert_eq!( config_after, config_before, - "Tier configuration must remain unchanged regardless of slot_number_args." + "Tier configuration must remain unchanged." ); }) } @@ -4137,23 +4134,13 @@ fn set_static_tier_params_invalid_params_fails() { Error::::InvalidTierParams ); - // invalid dynamic percentage (min > max) - let mut tier_thresholds = tier_params.tier_thresholds.clone().to_vec(); - tier_thresholds[0] = TierThreshold::DynamicPercentage { - percentage: Perbill::from_percent(2), - minimum_required_percentage: Perbill::from_percent(5), - maximum_possible_percentage: Perbill::from_percent(3), - }; - - let invalid_min_max_params = TierParameters:: { - tier_thresholds: tier_thresholds.try_into().unwrap(), - ..tier_params.clone() - }; - - assert!(!invalid_min_max_params.is_valid(), "Invalid min/max"); + // invalid tier rank multiplier (tier 0 exceeds 10_000) + let mut bad_params = tier_params.clone(); + bad_params.tier_rank_multipliers[0] = 20_000; + assert!(!bad_params.is_valid(), "Invalid tier rank multiplier"); assert_noop!( - DappStaking::set_static_tier_params(RuntimeOrigin::root(), invalid_min_max_params), + DappStaking::set_static_tier_params(RuntimeOrigin::root(), bad_params), Error::::InvalidTierParams ); }) diff --git a/pallets/dapp-staking/src/test/tests_types.rs b/pallets/dapp-staking/src/test/tests_types.rs index 25564a0ae..56a83e219 100644 --- a/pallets/dapp-staking/src/test/tests_types.rs +++ b/pallets/dapp-staking/src/test/tests_types.rs @@ -17,7 +17,7 @@ // along with Astar. If not, see . use astar_primitives::{ - dapp_staking::{RankedTier, FIXED_NUMBER_OF_TIER_SLOTS, FIXED_TIER_SLOTS_ARGS}, + dapp_staking::{RankedTier, FIXED_NUMBER_OF_TIER_SLOTS}, Balance, }; use frame_support::assert_ok; @@ -3486,7 +3486,6 @@ fn tier_params_check_is_ok() { }, ]) .unwrap(), - slot_number_args: FIXED_TIER_SLOTS_ARGS, tier_rank_multipliers: BoundedVec::try_from(vec![10_000, 24_000, 46_700]).unwrap(), }; assert!(params.is_valid()); @@ -3535,45 +3534,7 @@ fn tier_params_check_is_ok() { .unwrap(); assert!(!new_params.is_valid()); - // 5th scenario - DynamicPercentage with valid min/max (min <= max) - let mut valid_dynamic_params = params.clone(); - valid_dynamic_params.tier_thresholds = BoundedVec::try_from(vec![ - TierThreshold::DynamicPercentage { - percentage: Perbill::from_percent(2), - minimum_required_percentage: Perbill::from_percent(1), - maximum_possible_percentage: Perbill::from_percent(3), - }, - TierThreshold::DynamicPercentage { - percentage: Perbill::from_percent(2), - minimum_required_percentage: Perbill::from_percent(2), // equal min and max is valid - maximum_possible_percentage: Perbill::from_percent(2), - }, - TierThreshold::FixedPercentage { - required_percentage: Perbill::from_percent(1), - }, - ]) - .unwrap(); - assert!(valid_dynamic_params.is_valid()); - - // 6th scenario - DynamicPercentage with invalid min/max (min > max) - let mut invalid_dynamic_params = params.clone(); - invalid_dynamic_params.tier_thresholds = BoundedVec::try_from(vec![ - TierThreshold::DynamicPercentage { - percentage: Perbill::from_percent(2), - minimum_required_percentage: Perbill::from_percent(4), // min > max is invalid - maximum_possible_percentage: Perbill::from_percent(3), - }, - TierThreshold::FixedPercentage { - required_percentage: Perbill::from_percent(2), - }, - TierThreshold::FixedPercentage { - required_percentage: Perbill::from_percent(1), - }, - ]) - .unwrap(); - assert!(!invalid_dynamic_params.is_valid()); - - // 7th scenario - tier_rank_multipliers length mismatch with number of tiers + // 5th scenario - tier_rank_multipliers length mismatch with number of tiers let mut invalid_tier_points = params.clone(); invalid_tier_points.tier_rank_multipliers = BoundedVec::try_from(vec![ 10_000, 24_000, @@ -3627,7 +3588,6 @@ fn tier_configuration_basic_tests() { }, ]) .unwrap(), - slot_number_args: FIXED_TIER_SLOTS_ARGS, tier_rank_multipliers: BoundedVec::try_from(vec![0, 24_000, 46_700, 0]).unwrap(), }; assert!(params.is_valid(), "Example params must be valid!"); @@ -3808,10 +3768,8 @@ fn tier_thresholds_conversion_test() { TierThreshold::FixedPercentage { required_percentage: Perbill::from_percent(10), }, - TierThreshold::DynamicPercentage { - percentage: Perbill::from_percent(5), - minimum_required_percentage: Perbill::from_percent(2), - maximum_possible_percentage: Perbill::from_percent(100), + TierThreshold::FixedPercentage { + required_percentage: Perbill::from_percent(5), }, ]) .unwrap(); @@ -3828,7 +3786,7 @@ fn tier_thresholds_conversion_test() { } #[test] -fn tier_configuration_calculate_new_with_maximum_threshold() { +fn tier_configuration_calculate_new_with_fixed_thresholds() { get_u32_type!(TiersNum, 4); let slot_distribution = BoundedVec::::try_from(vec![ @@ -3847,22 +3805,15 @@ fn tier_configuration_calculate_new_with_maximum_threshold() { ]) .unwrap(); - // Thresholds with explicit min/max clamping behavior. let tier_thresholds = BoundedVec::::try_from(vec![ - TierThreshold::DynamicPercentage { - percentage: Perbill::from_percent(9), - minimum_required_percentage: Perbill::from_percent(3), - maximum_possible_percentage: Perbill::from_percent(5), + TierThreshold::FixedPercentage { + required_percentage: Perbill::from_percent(9), }, - TierThreshold::DynamicPercentage { - percentage: Perbill::from_percent(1), - minimum_required_percentage: Perbill::from_percent(2), - maximum_possible_percentage: Perbill::from_percent(4), + TierThreshold::FixedPercentage { + required_percentage: Perbill::from_percent(2), }, - TierThreshold::DynamicPercentage { - percentage: Perbill::from_percent(2), - minimum_required_percentage: Perbill::from_percent(1), - maximum_possible_percentage: Perbill::from_percent(3), + TierThreshold::FixedPercentage { + required_percentage: Perbill::from_percent(1), }, TierThreshold::FixedPercentage { required_percentage: Perbill::from_parts(5_000_000), // 0.5% @@ -3874,11 +3825,9 @@ fn tier_configuration_calculate_new_with_maximum_threshold() { slot_distribution, tier_thresholds, reward_portion: reward_portion.clone(), - slot_number_args: FIXED_TIER_SLOTS_ARGS, tier_rank_multipliers: BoundedVec::try_from(vec![0, 24_000, 46_700, 0]).unwrap(), }; - // Create a starting configuration with placeholder values. let total_issuance: Balance = 8_400_000_000; let init_config = TiersConfiguration:: { @@ -3890,25 +3839,18 @@ fn tier_configuration_calculate_new_with_maximum_threshold() { let new_config = init_config.calculate_new(¶ms, total_issuance); - // Clamped to maximum. assert_eq!( new_config.tier_thresholds[0], - Perbill::from_percent(5) * total_issuance + Perbill::from_percent(9) * total_issuance ); - - // Clamped to minimum. assert_eq!( new_config.tier_thresholds[1], Perbill::from_percent(2) * total_issuance ); - - // Within bounds, unchanged. assert_eq!( new_config.tier_thresholds[2], - Perbill::from_percent(2) * total_issuance + Perbill::from_percent(1) * total_issuance ); - - // Fixed threshold remains fixed. assert_eq!( new_config.tier_thresholds[3], Perbill::from_parts(5_000_000) * total_issuance diff --git a/pallets/dapp-staking/src/types.rs b/pallets/dapp-staking/src/types.rs index 6c720ce97..67f49afb8 100644 --- a/pallets/dapp-staking/src/types.rs +++ b/pallets/dapp-staking/src/types.rs @@ -86,7 +86,7 @@ pub type AccountLedgerFor = AccountLedger<::MaxUnlockingChunks>; // Convenience type for `DAppTierRewards` usage. pub type DAppTierRewardsFor = - DAppTierRewards<::MaxNumberOfContractsLegacy, ::NumberOfTiers>; + DAppTierRewards<::MaxNumberOfContracts, ::NumberOfTiers>; // Convenience type for `EraRewardSpan` usage. pub type EraRewardSpanFor = EraRewardSpan<::EraRewardSpanLength>; @@ -1651,25 +1651,12 @@ pub enum TierThreshold { /// Entry into the tier is mandated by a fixed percentage of the total issuance as staked funds. /// This value is constant and does not change between periods. FixedPercentage { required_percentage: Perbill }, - /// Entry into the tier is mandated by a percentage of the total issuance as staked funds. - /// This `percentage` can change between periods, but must stay within the defined - /// `minimum_required_percentage` and `maximum_possible_percentage`. - /// If minimum is greater than maximum, the configuration is invalid. - /// - /// NOTE: It's up to the user to ensure that minimum_required_percentage is - /// less than or equal to maximum_possible_percentage to avoid potential issues. - DynamicPercentage { - percentage: Perbill, - minimum_required_percentage: Perbill, - maximum_possible_percentage: Perbill, - }, } impl TierThreshold { /// Return threshold amount for the tier. pub fn threshold(&self, total_issuance: Balance) -> Balance { match self { - Self::DynamicPercentage { percentage, .. } => *percentage * total_issuance, Self::FixedPercentage { required_percentage, } => *required_percentage * total_issuance, @@ -1705,11 +1692,6 @@ pub struct TierParameters> { /// Requirements for entry into each tier. /// First entry refers to the first tier, and so on. pub(crate) tier_thresholds: BoundedVec, - /// Legacy arguments for the linear equation used to calculate the number of slots. - /// - /// Kept for storage/config compatibility, but ignored during tier recalculation. - /// Tier slot count is fixed via `FIXED_NUMBER_OF_TIER_SLOTS` in `TiersConfiguration::calculate_new`. - pub(crate) slot_number_args: (u64, u64), /// Rank multiplier per tier in bips (100% = 10_000 bips): /// defines how much rank 10 earns relative to rank 0. /// @@ -1751,20 +1733,6 @@ impl> TierParameters { return false; } - // Validate that the minimum percentage is less than or equal to maximum percentage. - for threshold in self.tier_thresholds.iter() { - if let TierThreshold::DynamicPercentage { - minimum_required_percentage, - maximum_possible_percentage, - .. - } = threshold - { - if minimum_required_percentage > maximum_possible_percentage { - return false; - } - } - } - // - Tier 0: must be <= 100% (no rank bonus for the top tier) match self.tier_rank_multipliers.first() { Some(m0) if *m0 <= 10_000 => {} @@ -1864,21 +1832,7 @@ impl> TiersConfiguration { .tier_thresholds .clone() .iter() - .map(|threshold| match threshold { - TierThreshold::DynamicPercentage { - percentage, - minimum_required_percentage, - maximum_possible_percentage, - } => { - let amount = *percentage * total_issuance; - let minimum_amount = *minimum_required_percentage * total_issuance; - let maximum_amount = *maximum_possible_percentage * total_issuance; - amount.max(minimum_amount).min(maximum_amount) - } - TierThreshold::FixedPercentage { - required_percentage, - } => *required_percentage * total_issuance, - }) + .map(|threshold| threshold.threshold(total_issuance)) .collect::>() .try_into() .unwrap_or_default(); diff --git a/pallets/price-aggregator/Cargo.toml b/pallets/price-aggregator/Cargo.toml deleted file mode 100644 index 7a67c3f05..000000000 --- a/pallets/price-aggregator/Cargo.toml +++ /dev/null @@ -1,68 +0,0 @@ -[package] -name = "pallet-price-aggregator" -version = "0.1.0" -license = "GPL-3.0-or-later" -description = "Price aggregation & moving average calculation support." -authors.workspace = true -edition.workspace = true -homepage.workspace = true -repository.workspace = true - -[lints] -workspace = true - -[dependencies] -log = { workspace = true } -parity-scale-codec = { workspace = true } -serde = { workspace = true } - -astar-primitives = { workspace = true } -frame-support = { workspace = true } -frame-system = { workspace = true } -scale-info = { workspace = true } -sp-arithmetic = { workspace = true } -sp-runtime = { workspace = true } -sp-std = { workspace = true } - -orml-traits = { workspace = true } - -frame-benchmarking = { workspace = true, optional = true } - -[dev-dependencies] -num-traits = { workspace = true } -pallet-balances = { workspace = true } -sp-core = { workspace = true } -sp-io = { workspace = true } - -[features] -default = ["std"] -std = [ - "parity-scale-codec/std", - "log/std", - "sp-core/std", - "scale-info/std", - "serde/std", - "sp-std/std", - "frame-support/std", - "frame-system/std", - "pallet-balances/std", - "astar-primitives/std", - "sp-arithmetic/std", - "orml-traits/std", - "frame-benchmarking?/std", - "sp-runtime/std", -] -runtime-benchmarks = [ - "frame-benchmarking", - "frame-support/runtime-benchmarks", - "frame-system/runtime-benchmarks", - "sp-runtime/runtime-benchmarks", - "astar-primitives/runtime-benchmarks", - "frame-benchmarking/runtime-benchmarks", -] -try-runtime = [ - "frame-support/try-runtime", - "astar-primitives/try-runtime", - "frame-system/try-runtime", - "sp-runtime/try-runtime", -] diff --git a/pallets/price-aggregator/src/benchmarking.rs b/pallets/price-aggregator/src/benchmarking.rs deleted file mode 100644 index cb5d772a2..000000000 --- a/pallets/price-aggregator/src/benchmarking.rs +++ /dev/null @@ -1,102 +0,0 @@ -// This file is part of Astar. - -// Copyright (C) Stake Technologies Pte.Ltd. -// SPDX-License-Identifier: GPL-3.0-or-later - -// Astar is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. - -// Astar is distributed in the hope that it will be useful, -// 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. - -// You should have received a copy of the GNU General Public License -// along with Astar. If not, see . - -#![cfg(feature = "runtime-benchmarks")] - -use super::*; -use frame_benchmarking::v2::*; - -#[benchmarks] -mod benchmarks { - use super::*; - - #[benchmark] - fn process_block_aggregated_values() { - // Fill up the current block buffer with some values - let size_limit = ::MaxValuesPerBlock::get(); - let mut result = BoundedVec::::MaxValuesPerBlock>::default(); - for x in 1..=size_limit { - let value = CurrencyAmount::from_rational(x as u128 + 3, 10); - result - .try_push(value) - .expect("Must succeed since we are iterating to the limit"); - } - CurrentBlockValues::::put(result); - - #[block] - { - Pallet::::process_block_aggregated_values(); - } - - assert!( - CurrentBlockValues::::get().is_empty(), - "Should have been cleaned up." - ); - } - - #[benchmark] - fn process_intermediate_aggregated_values() { - // 1. Fill up the current aggregator and make it trigger on the current block end - IntermediateValueAggregator::::mutate(|a| { - a.limit_block = frame_system::Pallet::::block_number().saturated_into(); - - a.total = CurrencyAmount::from_rational(1234, 10); - a.count = 19; - }); - - // 2. Fill up the circular buffer with some values - let buffer_length = ::CircularBufferLength::get(); - ValuesCircularBuffer::::mutate(|b| { - for x in 1..=buffer_length { - b.add(CurrencyAmount::from_rational(x as u128 + 3, 10)); - } - }); - assert_eq!( - ValuesCircularBuffer::::get().buffer.len(), - buffer_length as usize, - "Sanity check." - ); - - // 3. Prepare local variables - let buffer_snapshot = ValuesCircularBuffer::::get(); - let current_block = frame_system::Pallet::::block_number(); - - #[block] - { - Pallet::::process_intermediate_aggregated_values(current_block); - } - - assert!(ValuesCircularBuffer::::get() != buffer_snapshot); - } - - impl_benchmark_test_suite!( - Pallet, - crate::benchmarking::tests::new_test_ext(), - crate::mock::Test, - ); -} - -#[cfg(test)] -mod tests { - use crate::mock; - use sp_io::TestExternalities; - - pub fn new_test_ext() -> TestExternalities { - mock::ExtBuilder::build() - } -} diff --git a/pallets/price-aggregator/src/lib.rs b/pallets/price-aggregator/src/lib.rs deleted file mode 100644 index fabee5af8..000000000 --- a/pallets/price-aggregator/src/lib.rs +++ /dev/null @@ -1,473 +0,0 @@ -// This file is part of Astar. - -// Copyright (C) Stake Technologies Pte.Ltd. -// SPDX-License-Identifier: GPL-3.0-or-later - -// Astar is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. - -// Astar is distributed in the hope that it will be useful, -// 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. - -// You should have received a copy of the GNU General Public License -// along with Astar. If not, see . - -//! # Price Aggregator Pallet -//! -//! ## Overview -//! -//! Purpose of this pallet is to aggregate price data over some time, and then calculate the moving average. -//! -//! ## Solution -//! -//! The overall solution is broken down into several steps that occur over the course of various time periods. -//! -//! ### Block Aggregation -//! -//! During each block, the native currency price data is accumulated. This is done 'outside' the pallet, and it's only expected -//! that 'something' will push this data to the price aggregator pallet. The pallet itself doesn't care about the source of the data, nor who submitted it. -//! -//! At the end of each block, accumulated data is processed according to the specified algorithm (e.g. can be average, median, or something else). -//! In case processing was successful, the result is stored in the intermediate value aggregator. -//! In case processing fails, value is simply ignored. -//! -//! ### Intermediate Value Aggregation -//! -//! After a predetermined amount of time (blocks) has passed, the average value is calculated from the intermediate value aggregator. -//! In case it's a valid value (non-zero), it's pushed into the circular buffer used to calculate the moving average. -//! In case of an error, the value is simply ignored. -//! -//! ### Moving Average Calculation -//! -//! The moving average is calculated from the circular buffer, and is used to provide the 'average' price of the native currency, over some time period. -//! It's important to note that the moving average is not a 'real-time' value, but rather a 'lagging' indicator. - -#![cfg_attr(not(feature = "std"), no_std)] - -use frame_support::{pallet_prelude::*, DefaultNoBound}; -use frame_system::pallet_prelude::*; -pub use pallet::*; -use sp_arithmetic::{ - fixed_point::FixedU128, - traits::{CheckedAdd, SaturatedConversion, Saturating, Zero}, -}; -use sp_std::marker::PhantomData; - -use orml_traits::OnNewData; - -use astar_primitives::{ - oracle::{CurrencyAmount, CurrencyId, PriceProvider}, - BlockNumber, -}; - -pub mod weights; -pub use weights::WeightInfo; - -#[cfg(test)] -mod mock; -#[cfg(test)] -mod tests; - -#[cfg(feature = "runtime-benchmarks")] -mod benchmarking; - -/// Trait for processing accumulated currency values within a single block. -/// -/// This can be anything from median, average, or more complex calculation. -pub trait ProcessBlockValues { - /// Process the accumulated values and return the result. - /// - /// In case of an error, return an error message. - fn process(values: &[CurrencyAmount]) -> Result; -} - -/// Used to calculate the simple average of the accumulated values. -pub struct AverageBlockValue; -impl ProcessBlockValues for AverageBlockValue { - fn process(values: &[CurrencyAmount]) -> Result { - if values.is_empty() { - return Err("No values exist for the current block."); - } - - let sum = values.iter().fold(CurrencyAmount::zero(), |acc, &value| { - acc.saturating_add(value) - }); - - Ok(sum.saturating_mul(FixedU128::from_rational(1, values.len() as u128))) - } -} - -/// Used to calculate the median of the accumulated values. -pub struct MedianBlockValue; -impl ProcessBlockValues for MedianBlockValue { - fn process(values: &[CurrencyAmount]) -> Result { - if values.is_empty() { - return Err("No values exist for the current block."); - } - - let mut sorted_values = values.to_vec(); - sorted_values.sort_unstable(); - - let mid = sorted_values.len() / 2; - - if sorted_values.len() % 2 == 0 { - Ok(sorted_values[mid.saturating_sub(1)] - .saturating_add(sorted_values[mid]) - .saturating_mul(CurrencyAmount::from_rational(1, 2))) - } else { - Ok(sorted_values[mid]) - } - } -} - -/// Used to aggregate the accumulated values over some time period. -/// -/// To avoid having a large memory footprint, values are summed up into a single accumulator. -/// Number of summed up values is tracked in a separate field. -#[derive(Encode, Decode, MaxEncodedLen, Default, Clone, Copy, Debug, PartialEq, Eq, TypeInfo)] -pub struct ValueAggregator { - /// Total accumulated value amount. - #[codec(compact)] - pub(crate) total: CurrencyAmount, - /// Number of values accumulated. - #[codec(compact)] - pub(crate) count: u32, - /// Block number at which aggregation should reset. - #[codec(compact)] - pub(crate) limit_block: BlockNumber, -} - -impl ValueAggregator { - /// New value aggregator, with the given block number as the new limit. - pub fn new(limit_block: BlockNumber) -> Self { - Self { - limit_block, - ..Default::default() - } - } - - /// Attempts to add a value to the aggregator, consuming `self` in the process. - /// - /// Returns an error if the addition would cause an overflow in the accumulator or the counter. - /// Otherwise returns the updated aggregator. - pub fn try_add(mut self, value: CurrencyAmount) -> Result { - self.total = self - .total - .checked_add(&value) - .ok_or("Failed to add value to the aggregator due to overflow.")?; - - self.count = self - .count - .checked_add(1) - .ok_or("Failed to increment count in the aggregator due to overflow.")?; - - Ok(self) - } - - /// Returns the average of the accumulated values. - pub fn average(&self) -> CurrencyAmount { - if self.count.is_zero() { - CurrencyAmount::zero() - } else { - self.total - .saturating_mul(FixedU128::from_rational(1, self.count.into())) - } - } -} - -/// Used to store the aggregated intermediate values into a circular buffer. -/// -/// Inserts values sequentially into the buffer, until the buffer has been filled out. -/// After that, the oldest value is always overwritten with the new value. -#[derive( - Encode, - Decode, - MaxEncodedLen, - RuntimeDebugNoBound, - PartialEqNoBound, - EqNoBound, - CloneNoBound, - TypeInfo, - DefaultNoBound, -)] -#[scale_info(skip_type_params(L))] -pub struct CircularBuffer> { - /// Currency values store. - pub(crate) buffer: BoundedVec, - /// Next index to write to. - #[codec(compact)] - pub(crate) head: u32, -} - -impl> CircularBuffer { - /// Adds a new value to the circular buffer, possibly overriding the oldest value if capacity is filled. - pub fn add(&mut self, value: CurrencyAmount) { - // This can never happen, parameters must ensure that. - // But we still check it and log an error if it does. - if self.head >= L::get() || self.head as usize > self.buffer.len() { - log::error!( - target: LOG_TARGET, - "Failed to push value to the circular buffer due to invalid next index. \ - Next index: {:?}, Buffer length: {:?}, Buffer capacity: {:?}", - self.head, - self.buffer.len(), - L::get() - ); - return; - } - - if self.buffer.len() > self.head as usize { - // Vec has been filled out, so we need to override the 'head' value - self.buffer[self.head as usize] = value; - } else { - // Vec is not full yet, so we can just push the value - let _ignorable = self.buffer.try_push(value); - } - self.head = self.head.saturating_add(1) % L::get(); - } - - /// Returns the average of the accumulated values. - pub fn average(&self) -> CurrencyAmount { - if self.buffer.is_empty() { - return CurrencyAmount::zero(); - } - - let sum = self - .buffer - .iter() - .fold(CurrencyAmount::zero(), |acc, &value| { - acc.saturating_add(value) - }); - - // At this point, length of the buffer is guaranteed to be greater than zero. - sum.saturating_mul(FixedU128::from_rational(1, self.buffer.len() as u128)) - } -} - -const LOG_TARGET: &str = "price-aggregator"; - -#[frame_support::pallet] -pub mod pallet { - use super::*; - - /// The current storage version. - pub const STORAGE_VERSION: StorageVersion = StorageVersion::new(1); - - #[pallet::pallet] - #[pallet::storage_version(STORAGE_VERSION)] - pub struct Pallet(PhantomData); - - #[pallet::config] - pub trait Config: frame_system::Config { - /// Maximum number of distinct currency values we can store during a single block. - #[pallet::constant] - type MaxValuesPerBlock: Get; - - /// Used to process accumulated values in the current block. - type ProcessBlockValues: ProcessBlockValues; - - /// Native currency ID that this pallet is supposed to track. - type NativeCurrencyId: Get; - - /// Maximum length of the circular buffer used to calculate the moving average. - #[pallet::constant] - type CircularBufferLength: Get; - - /// Duration of aggregation period expressed in the number of blocks. - /// During this time, currency values are aggregated, and are then used to calculate the average value. - #[pallet::constant] - type AggregationDuration: Get>; - - type WeightInfo: WeightInfo; - } - - #[pallet::genesis_config] - #[derive(frame_support::DefaultNoBound)] - pub struct GenesisConfig { - pub circular_buffer: BoundedVec, - } - - #[pallet::genesis_build] - impl BuildGenesisConfig for GenesisConfig { - fn build(&self) { - ValuesCircularBuffer::::put(CircularBuffer:: { - buffer: self.circular_buffer.clone(), - head: self.circular_buffer.len() as u32 % T::CircularBufferLength::get(), - }); - - IntermediateValueAggregator::::mutate(|aggregator| { - aggregator.limit_block = T::AggregationDuration::get().saturated_into(); - }); - } - } - - #[pallet::event] - #[pallet::generate_deposit(pub(crate) fn deposit_event)] - pub enum Event { - /// New average native currency value has been calculated and pushed into the moving average buffer. - AverageAggregatedValue { value: CurrencyAmount }, - } - - /// Storage for the accumulated native currency price in the current block. - #[pallet::storage] - #[pallet::whitelist_storage] - pub type CurrentBlockValues = - StorageValue<_, BoundedVec, ValueQuery>; - - /// Used to store the aggregated processed block values during some time period. - #[pallet::storage] - #[pallet::whitelist_storage] - pub type IntermediateValueAggregator = StorageValue<_, ValueAggregator, ValueQuery>; - - /// Used to store aggregated intermediate values for some time period. - #[pallet::storage] - pub type ValuesCircularBuffer = - StorageValue<_, CircularBuffer, ValueQuery>; - - #[pallet::hooks] - impl Hooks> for Pallet { - fn on_initialize(now: BlockNumberFor) -> Weight { - // Need to account for the reads and writes of: - // - CurrentBlockValues - // - IntermediateValueAggregator - // - // Also need to account for the weight of processing block accumulated values. - let mut total_weight = T::DbWeight::get() - .reads_writes(2, 2) - .saturating_add(T::WeightInfo::process_block_aggregated_values()); - - if IntermediateValueAggregator::::get().limit_block <= now.saturated_into() { - total_weight - .saturating_accrue(T::WeightInfo::process_intermediate_aggregated_values()); - } - - total_weight - } - - fn on_finalize(now: BlockNumberFor) { - // 1. Process the accumulated native currency values in the current block. - Self::process_block_aggregated_values(); - - // 2. Check if we need to push the average aggregated value to the storage. - if IntermediateValueAggregator::::get().limit_block <= now.saturated_into() { - Self::process_intermediate_aggregated_values(now); - } - } - - fn integrity_test() { - assert!(T::MaxValuesPerBlock::get() > 0); - assert!(T::CircularBufferLength::get() > 0); - assert!(!T::AggregationDuration::get().is_zero()); - } - } - - impl Pallet { - /// Used to process the native currency values accumulated in the current block. - /// - /// Guarantees that the accumulated values are cleared after processing. - /// In case of an error during processing, intermediate aggregated value is not updated. - pub(crate) fn process_block_aggregated_values() { - // 1. Take the accumulated block values, clearing the existing storage. - let accumulated_values = CurrentBlockValues::::take(); - - // 2. Attempt to process accumulated block values. - let processed_value = match T::ProcessBlockValues::process( - accumulated_values.as_slice(), - ) { - Ok(value) => value, - Err(message) => { - log::trace!( - target: LOG_TARGET, - "Failed to process the accumulated native currency values in the current block. \ - Reason: {:?}", - message - ); - - // Nothing to do if we have no valid value to store. - return; - } - }; - - // 3. Attempt to store the processed value. - // This operation is practically infallible, but we check the results for the additional safety. - let intermediate_value = IntermediateValueAggregator::::get(); - match intermediate_value.try_add(processed_value) { - Ok(new_aggregator) => { - IntermediateValueAggregator::::put(new_aggregator); - } - Err(message) => { - log::error!( - target: LOG_TARGET, - "Failed to add the processed native currency value to the intermediate storage. \ - Reason: {:?}", - message - ); - } - } - } - - /// Used to process the intermediate aggregated values, and push them to the moving average storage. - pub(crate) fn process_intermediate_aggregated_values(now: BlockNumberFor) { - // 1. Get the average value from the intermediate aggregator. - let average_value = IntermediateValueAggregator::::get().average(); - - // 2. Reset the aggregator back to zero, and set the new limit block. - IntermediateValueAggregator::::put(ValueAggregator::new( - now.saturating_add(T::AggregationDuration::get()) - .saturated_into(), - )); - - // 3. In case aggregated value equals 0, it means something has gone wrong since it's extremely unlikely - // that price goes to absolute zero. The much more likely case is that there's a problem with the oracle data feed. - if average_value.is_zero() { - log::error!( - target: LOG_TARGET, - "The average aggregated price equals zero, which most likely means that oracle data feed is faulty. \ - Not pushing the 'zero' value to the moving average storage." - ); - return; - } - - // 4. Push the 'valid' average aggregated value to the circular buffer. - ValuesCircularBuffer::::mutate(|buffer| buffer.add(average_value)); - Self::deposit_event(Event::AverageAggregatedValue { - value: average_value, - }); - } - } - - // Make this pallet an 'observer' ('listener') of the new oracle data feed. - impl OnNewData for Pallet { - fn on_new_data(who: &T::AccountId, key: &CurrencyId, value: &CurrencyAmount) { - // Ignore any currency that is not native currency. - if T::NativeCurrencyId::get() != *key { - return; - } - - CurrentBlockValues::::mutate(|v| match v.try_push(*value) { - Ok(()) => {} - Err(_) => { - log::error!( - target: LOG_TARGET, - "Failed to push native currency value into the ongoing block due to exceeded capacity. \ - Value was submitted by: {:?}", - who - ); - } - }); - } - } - - // Make this pallet a `price provider` for the native currency. - // - // For this particular implementation, a simple moving average is used to calculate the average price. - impl PriceProvider for Pallet { - fn average_price() -> FixedU128 { - ValuesCircularBuffer::::get().average() - } - } -} diff --git a/pallets/price-aggregator/src/mock.rs b/pallets/price-aggregator/src/mock.rs deleted file mode 100644 index 0721c7ed0..000000000 --- a/pallets/price-aggregator/src/mock.rs +++ /dev/null @@ -1,100 +0,0 @@ -// This file is part of Astar. - -// Copyright (C) Stake Technologies Pte.Ltd. -// SPDX-License-Identifier: GPL-3.0-or-later - -// Astar is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. - -// Astar is distributed in the hope that it will be useful, -// 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. - -// You should have received a copy of the GNU General Public License -// along with Astar. If not, see . - -use crate::{ - self as pallet_price_aggregator, AverageBlockValue, BlockNumberFor, IntermediateValueAggregator, -}; - -use frame_support::{ - construct_runtime, derive_impl, parameter_types, - traits::{ConstU128, ConstU32, Hooks}, - weights::Weight, -}; -use sp_io::TestExternalities; -use sp_runtime::BuildStorage; - -use astar_primitives::{oracle::CurrencyId, Balance, BlockNumber}; - -type Block = frame_system::mocking::MockBlockU32; - -parameter_types! { - pub const BlockHashCount: BlockNumber = 250; - pub BlockWeights: frame_system::limits::BlockWeights = - frame_system::limits::BlockWeights::simple_max(Weight::from_parts(1024, 0)); -} - -#[derive_impl(frame_system::config_preludes::TestDefaultConfig)] -impl frame_system::Config for Test { - type Block = Block; - type AccountData = pallet_balances::AccountData; -} - -#[derive_impl(pallet_balances::config_preludes::TestDefaultConfig)] -impl pallet_balances::Config for Test { - type Balance = Balance; - type ExistentialDeposit = ConstU128<1>; - type AccountStore = System; -} - -parameter_types! { - pub const NativeCurrencyId: CurrencyId = CurrencyId::ASTR; - pub const AggregationDuration: BlockNumberFor = 16; -} - -impl pallet_price_aggregator::Config for Test { - // Should at least be 3 for tests to work properly - type MaxValuesPerBlock = ConstU32<4>; - type ProcessBlockValues = AverageBlockValue; - type NativeCurrencyId = NativeCurrencyId; - type CircularBufferLength = ConstU32<7>; - type AggregationDuration = AggregationDuration; - type WeightInfo = (); -} - -construct_runtime!( - pub struct Test { - System: frame_system, - Balances: pallet_balances, - PriceAggregator: pallet_price_aggregator, - } -); - -pub struct ExtBuilder; -impl ExtBuilder { - pub fn build() -> TestExternalities { - let storage = frame_system::GenesisConfig::::default() - .build_storage() - .unwrap(); - - let mut ext = TestExternalities::from(storage); - ext.execute_with(|| { - // 1. Set the initial limit block for the intermediate value aggregator - IntermediateValueAggregator::::mutate(|v| { - v.limit_block = - ::AggregationDuration::get() + 1 - }); - - // 2. Init block setting - let init_block_number = 1; - System::set_block_number(init_block_number); - PriceAggregator::on_initialize(init_block_number); - }); - - ext - } -} diff --git a/pallets/price-aggregator/src/tests.rs b/pallets/price-aggregator/src/tests.rs deleted file mode 100644 index 75d528948..000000000 --- a/pallets/price-aggregator/src/tests.rs +++ /dev/null @@ -1,562 +0,0 @@ -// This file is part of Astar. - -// Copyright (C) Stake Technologies Pte.Ltd. -// SPDX-License-Identifier: GPL-3.0-or-later - -// Astar is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. - -// Astar is distributed in the hope that it will be useful, -// 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. - -// You should have received a copy of the GNU General Public License -// along with Astar. If not, see . - -use crate::mock::*; -use crate::{ - pallet::Config, AverageBlockValue, CircularBuffer, CurrentBlockValues, Event, - IntermediateValueAggregator, MedianBlockValue, ProcessBlockValues, ValueAggregator, - ValuesCircularBuffer, -}; - -use astar_primitives::oracle::{CurrencyAmount, CurrencyId}; - -use orml_traits::OnNewData; - -use frame_support::{ - assert_storage_noop, - traits::{Get, Hooks}, - BoundedVec, -}; -use sp_runtime::{traits::Zero, Saturating}; - -pub use num_traits::Bounded; - -#[test] -fn average_block_value_works() { - // 0. Empty vec check - let empty_vec: Vec = vec![]; - assert!(AverageBlockValue::process(&empty_vec).is_err()); - - // 1. Single value check - let single_value_vec = vec![CurrencyAmount::from_rational(15, 10)]; - assert_eq!( - AverageBlockValue::process(&single_value_vec), - Ok(single_value_vec[0]) - ); - - // 2. Multiple values check - let multiple_values_vec = vec![ - CurrencyAmount::from_rational(5, 10), - CurrencyAmount::from_rational(15, 10), - ]; - assert_eq!( - AverageBlockValue::process(&multiple_values_vec), - Ok(CurrencyAmount::from_rational(10, 10)) - ); -} - -#[test] -fn median_block_value_works() { - // 0. Empty vec check - let empty_vec: Vec = vec![]; - assert!(MedianBlockValue::process(&empty_vec).is_err()); - - // 1. Single value check - let single_value_vec = vec![CurrencyAmount::from_rational(7, 10)]; - assert_eq!( - MedianBlockValue::process(&single_value_vec), - Ok(single_value_vec[0]) - ); - - // 2. Odd number values check - let odd_values_vec = vec![ - CurrencyAmount::from_rational(3, 10), - CurrencyAmount::from_rational(7, 10), - CurrencyAmount::from_rational(9, 10), - ]; - assert_eq!( - MedianBlockValue::process(&odd_values_vec), - Ok(CurrencyAmount::from_rational(7, 10)) - ); - - let odd_values_vec = vec![ - CurrencyAmount::from_rational(11, 10), - CurrencyAmount::from_rational(2, 10), - CurrencyAmount::from_rational(7, 10), - ]; - assert_eq!( - MedianBlockValue::process(&odd_values_vec), - Ok(CurrencyAmount::from_rational(7, 10)) - ); - - // 3.1. Even number values check - let even_values_vec_1 = vec![ - CurrencyAmount::from_rational(4, 10), - CurrencyAmount::from_rational(6, 10), - ]; - assert_eq!( - MedianBlockValue::process(&even_values_vec_1), - Ok(CurrencyAmount::from_rational(5, 10)) - ); - - let even_values_vec_1 = vec![ - CurrencyAmount::from_rational(6, 10), - CurrencyAmount::from_rational(4, 10), - ]; - assert_eq!( - MedianBlockValue::process(&even_values_vec_1), - Ok(CurrencyAmount::from_rational(5, 10)) - ); - - // 3.1. Even number values check - let even_values_vec_2 = vec![ - CurrencyAmount::from_rational(1, 10), - CurrencyAmount::from_rational(4, 10), - CurrencyAmount::from_rational(6, 10), - CurrencyAmount::from_rational(23, 10), - ]; - assert_eq!( - MedianBlockValue::process(&even_values_vec_2), - Ok(CurrencyAmount::from_rational(5, 10)) - ); - - let even_values_vec_2 = vec![ - CurrencyAmount::from_rational(23, 10), - CurrencyAmount::from_rational(4, 10), - CurrencyAmount::from_rational(3, 10), - CurrencyAmount::from_rational(6, 10), - ]; - assert_eq!( - MedianBlockValue::process(&even_values_vec_2), - Ok(CurrencyAmount::from_rational(5, 10)) - ); -} - -#[test] -fn value_aggregator_basic_checks() { - let limit_block = 10; - let value_aggregator = ValueAggregator::new(limit_block); - - // 0. Sanity checks - assert!(value_aggregator.total.is_zero()); - assert!(value_aggregator.count.is_zero()); - assert_eq!(value_aggregator.limit_block, limit_block); - assert!(value_aggregator.average().is_zero()); - - // 1. Add a value, verify state is as expected - let amount_1 = CurrencyAmount::from_rational(15, 10); - let result = value_aggregator.clone().try_add(amount_1); - assert_eq!( - result, - Ok(ValueAggregator { - total: amount_1, - count: 1, - limit_block, - }) - ); - assert_eq!(result.unwrap().average(), amount_1); - - // 2. Add another value, verify state is as expected - let value_aggregator = result.unwrap(); - let amount_2 = CurrencyAmount::from_rational(5, 10); - let result = value_aggregator.clone().try_add(amount_2); - assert_eq!( - result, - Ok(ValueAggregator { - total: amount_1 + amount_2, - count: 2, - limit_block, - }) - ); - assert_eq!( - result.unwrap().average(), - CurrencyAmount::from_rational(10, 10) - ); -} - -#[test] -fn value_aggregator_overflow_checks() { - // 1. Currency overflow check - let max_currency_aggregator = ValueAggregator { - total: CurrencyAmount::max_value(), - count: 10, - limit_block: 10, - }; - - let amount = CurrencyAmount::from_rational(1, 10); - let result = max_currency_aggregator.clone().try_add(amount); - assert!(result.is_err()); - - // 2. Counter overflow check - let max_count_aggregator = ValueAggregator { - total: CurrencyAmount::zero(), - count: u32::MAX, - limit_block: 10, - }; - let result = max_count_aggregator.clone().try_add(amount); - assert!(result.is_err()); -} - -#[test] -fn circular_buffer_basic_checks() { - // 0. Buffer size prep - const BUFFER_SIZE: u32 = 16; - struct BufferSize; - impl Get for BufferSize { - fn get() -> u32 { - BUFFER_SIZE - } - } - - // 1. Sanity checks - let mut circular_buffer = CircularBuffer::::default(); - assert!(circular_buffer.buffer.is_empty()); - assert!(circular_buffer.head.is_zero()); - - // 2. Add a value, verify state is as expected - let amount_1 = CurrencyAmount::from_rational(19, 10); - let mut expected_buffer = vec![amount_1]; - circular_buffer.add(amount_1); - assert_eq!(circular_buffer.buffer.clone().into_inner(), expected_buffer); - assert_eq!(circular_buffer.head, 1); - assert_eq!(circular_buffer.average(), amount_1); - - // 3. Add another value, verify state is as expected - let amount_2 = CurrencyAmount::from_rational(7, 10); - circular_buffer.add(amount_2); - expected_buffer.push(amount_2); - assert_eq!(circular_buffer.buffer.clone().into_inner(), expected_buffer); - assert_eq!(circular_buffer.head, 2); - assert_eq!( - circular_buffer.average(), - CurrencyAmount::from_rational(13, 10) - ); - - // 4. Fill up the buffer, verify state is as expected - let amount_3 = CurrencyAmount::from_rational(27, 10); - for _ in 2..BUFFER_SIZE { - circular_buffer.add(amount_3); - expected_buffer.push(amount_3); - } - assert_eq!(circular_buffer.buffer.clone().into_inner(), expected_buffer); - assert!(circular_buffer.head.is_zero()); - - // 5. Add another value, verify 0-th element is replaced - let amount_4 = CurrencyAmount::from_rational(9, 10); - circular_buffer.add(amount_4); - expected_buffer[0] = amount_4; - assert_eq!(circular_buffer.buffer.clone().into_inner(), expected_buffer); - assert_eq!(circular_buffer.head, 1); - - // 6. Repeat the cycle few more times, expect it works as expected - for x in 0..BUFFER_SIZE * 5 { - // Store head for the next check - let init_head = circular_buffer.head; - - // Generate a new amount - let amount = amount_3 * CurrencyAmount::from_rational(x as u128 + 1, 1); - - assert!(circular_buffer.buffer[init_head as usize] != amount); - circular_buffer.add(amount); - assert_eq!(circular_buffer.buffer[init_head as usize], amount); - assert_eq!(circular_buffer.head, (init_head + 1) % BUFFER_SIZE); - } -} - -#[test] -fn circular_buffer_inconsistency_safeguard_checks() { - // 0. Buffer size prep - const BUFFER_SIZE: u32 = 4; - struct BufferSize; - impl Get for BufferSize { - fn get() -> u32 { - BUFFER_SIZE - } - } - - // 1. Check that if head is ahead of length, operation does nothing - let amount = CurrencyAmount::from_rational(15, 100); - let mut inconsistent_buffer = CircularBuffer:: { - buffer: Default::default(), - head: 1, - }; - - inconsistent_buffer.add(amount); - assert!(inconsistent_buffer.buffer.is_empty()); - assert_eq!(inconsistent_buffer.head, 1); - - // 2. Check that when head equals length, operation does nothing - let init_buffer = BoundedVec::try_from(vec![amount, amount, amount, amount]) - .expect("Must work since size matches the bound."); - let mut inconsistent_buffer = CircularBuffer:: { - buffer: init_buffer.clone(), - head: BUFFER_SIZE, - }; - - inconsistent_buffer.add(amount); - assert_eq!(inconsistent_buffer.buffer, init_buffer); - assert_eq!(inconsistent_buffer.head, BUFFER_SIZE); -} - -#[test] -fn on_new_data_works_as_expected() { - ExtBuilder::build().execute_with(|| { - // 0. Initial sanity check - assert!( - CurrentBlockValues::::get().is_empty(), - "Init state must be empty." - ); - - // 1. Inform pallet of a new piece of data, verify state is as expected - let dummy_account_1 = 123; - let native_currency_id = ::NativeCurrencyId::get(); - let amount_1 = CurrencyAmount::from_rational(15, 10); - PriceAggregator::on_new_data(&dummy_account_1, &native_currency_id, &amount_1); - assert_eq!( - CurrentBlockValues::::get().into_inner(), - vec![amount_1], - ); - - // 2. Try to add non-native currency, verify no state change - let non_native_currency_id = CurrencyId::SDN; - assert!( - non_native_currency_id != native_currency_id, - "Sanity check." - ); - - let non_native_amount = CurrencyAmount::from_rational(7, 10); - assert_storage_noop!(PriceAggregator::on_new_data( - &dummy_account_1, - &non_native_currency_id, - &non_native_amount - )); - - // 3. Add additional amount, verify state is as expected - let amount_2 = CurrencyAmount::from_rational(3, 10); - PriceAggregator::on_new_data(&dummy_account_1, &native_currency_id, &amount_2); - assert_eq!( - CurrentBlockValues::::get().into_inner(), - vec![amount_1, amount_2], - ); - - // 4. Fill up storage to the limit, verify state is as expected - let limit = ::MaxValuesPerBlock::get(); - let mut result = vec![amount_1, amount_2]; - let amount_3 = CurrencyAmount::from_rational(19, 10); - - for _ in 2..limit { - PriceAggregator::on_new_data(&dummy_account_1, &native_currency_id, &amount_3); - result.push(amount_3); - } - - assert_eq!(result.len(), limit as usize, "Sanity check."); - assert_eq!(CurrentBlockValues::::get().into_inner(), result); - - // 5. Try to add one more value, overflowing the buffer, verify no state change - assert_storage_noop!(PriceAggregator::on_new_data( - &dummy_account_1, - &native_currency_id, - &amount_3 - )); - }); -} - -#[test] -fn on_finalize_updates_aggregated_data() { - ExtBuilder::build().execute_with(|| { - // 1. Store some data into the current block values buffer - let dummy_account_1 = 123; - let native_currency_id = ::NativeCurrencyId::get(); - let amount_1 = CurrencyAmount::from_rational(13, 10); - let amount_2 = CurrencyAmount::from_rational(17, 10); - PriceAggregator::on_new_data(&dummy_account_1, &native_currency_id, &amount_1); - PriceAggregator::on_new_data(&dummy_account_1, &native_currency_id, &amount_2); - - // 2. Finalize the block, verify state is as expected. - let block_number_1 = System::block_number(); - PriceAggregator::on_finalize(block_number_1); - - assert!( - CurrentBlockValues::::get().is_empty(), - "Buffer must be empty after the finalization." - ); - let intermediate_value_aggregator = IntermediateValueAggregator::::get(); - assert_eq!(intermediate_value_aggregator.count, 1); - - let average_amount_1 = CurrencyAmount::from_rational(15, 10); - assert_eq!(intermediate_value_aggregator.total, average_amount_1); - - // 3. Move to the next block, but for this one no new data is added - let intermediate_value_snapshot = IntermediateValueAggregator::::get(); - - let block_number_2 = block_number_1 + 1; - System::set_block_number(block_number_2); - PriceAggregator::on_initialize(block_number_2); - - // No new data is added, everything must still work without breaking - PriceAggregator::on_finalize(block_number_2); - assert_eq!( - IntermediateValueAggregator::::get(), - intermediate_value_snapshot, - "No new data was added, so the state must remain the same." - ); - - // 4. Add new data, verify state is updated as expected, i.e. nothing was broken by the previous step - let block_number_3 = block_number_2 + 1; - System::set_block_number(block_number_3); - PriceAggregator::on_initialize(block_number_3); - - let amount_3 = CurrencyAmount::from_rational(19, 10); - PriceAggregator::on_new_data(&dummy_account_1, &native_currency_id, &amount_3); - PriceAggregator::on_new_data(&dummy_account_1, &native_currency_id, &amount_3); - PriceAggregator::on_finalize(block_number_3); - - let intermediate_value_aggregator = IntermediateValueAggregator::::get(); - assert_eq!( - intermediate_value_aggregator.count, 2, - "Count must be 2 since we added only 2 new values." - ); - assert_eq!( - intermediate_value_aggregator.total, - average_amount_1 + amount_3, - "New entry must have been added, increasing the total." - ); - }) -} - -#[test] -fn on_finalize_updates_circular_buffer() { - ExtBuilder::build().execute_with(|| { - let dummy_account = 456; - let native_currency_id = ::NativeCurrencyId::get(); - - // 1. Advance just until limit block is reached, checking appropriate storage items along the way - let mut total = CurrencyAmount::zero(); - let current_block = System::block_number(); - let limit_block = IntermediateValueAggregator::::get().limit_block; - - for block in current_block..limit_block { - // Add new data - let amount = CurrencyAmount::from_rational(block.into(), 10); - PriceAggregator::on_new_data(&dummy_account, &native_currency_id, &amount); - total.saturating_accrue(amount); - - // Finalize the block - PriceAggregator::on_finalize(block); - assert_eq!( - IntermediateValueAggregator::::get().total, - total, - "Check total is updated as expected." - ); - assert!( - ValuesCircularBuffer::::get().buffer.is_empty(), - "Circular buffer is expected to remain empty until limit block is reached." - ); - - let new_block = block + 1; - System::set_block_number(new_block); - PriceAggregator::on_initialize(new_block); - } - - // 2. Move over to the next block, expect circular buffer to be updated since limit block will be reached. - let current_block = System::block_number(); - assert_eq!(current_block, limit_block, "Sanity check."); - - // Don't add any new data, just finalize the block. This is neat since we already know the exact 'total' amount - // but also get to test that circular buffer update doesn't break due to missing value. - PriceAggregator::on_finalize(current_block); - - // Check that value aggregator is reset & new block limit is correct - let reset_intermediate_aggregator = IntermediateValueAggregator::::get(); - assert_eq!(reset_intermediate_aggregator.total, CurrencyAmount::zero()); - assert_eq!(reset_intermediate_aggregator.count, 0); - assert_eq!( - reset_intermediate_aggregator.limit_block, - current_block + ::AggregationDuration::get() - ); - - // Check that circular buffer was updated as expected - let circular_buffer = ValuesCircularBuffer::::get(); - let expected_average = total * CurrencyAmount::from_rational(1, limit_block as u128 - 1); - assert_eq!( - circular_buffer.buffer.clone().into_inner(), - vec![expected_average] - ); - assert_eq!(circular_buffer.head, 1); - - // Verify deposited event - System::assert_last_event(RuntimeEvent::PriceAggregator( - Event::AverageAggregatedValue { - value: expected_average, - }, - )); - }) -} - -#[test] -fn circular_buffer_really_is_circular() { - ExtBuilder::build().execute_with(|| { - // 0. Init data - let aggregation_duration = ::AggregationDuration::get(); - let circular_buffer_length: u32 = ::CircularBufferLength::get(); - - fn advance_to_block(block: u32) { - let dummy_account = 456; - let native_currency_id = ::NativeCurrencyId::get(); - let init_block = System::block_number(); - - for block in init_block..block { - // Submit some amount to prevent error spam - let amount = CurrencyAmount::from_rational(block as u128, 10); - PriceAggregator::on_new_data(&dummy_account, &native_currency_id, &amount); - - PriceAggregator::on_finalize(block); - - let new_block = block + 1; - System::set_block_number(new_block); - PriceAggregator::on_initialize(new_block); - } - } - - // 1. Fill up the circular buffer - for x in 0..circular_buffer_length { - // Advance until circular buffer is updated - let intermediate_aggregator = IntermediateValueAggregator::::get(); - advance_to_block(intermediate_aggregator.limit_block + 1); - - // Check that circular buffer is updated as expected - let circular_buffer = ValuesCircularBuffer::::get(); - assert_eq!(circular_buffer.buffer.len(), x as usize + 1); - assert_eq!(circular_buffer.head, (x + 1) % circular_buffer_length); - - // Check that intermediate aggregator is reset & limit block is updated - let reset_intermediate_aggregator = IntermediateValueAggregator::::get(); - assert_eq!(reset_intermediate_aggregator.total, CurrencyAmount::zero()); - assert_eq!(reset_intermediate_aggregator.count, 0); - assert_eq!( - reset_intermediate_aggregator.limit_block, - intermediate_aggregator.limit_block + aggregation_duration - ); - } - - // 2. Continue adding the data, verify circular buffer is updated as expected - for x in 0..circular_buffer_length * 3 { - // Advance until circular buffer is updated - let intermediate_aggregator = IntermediateValueAggregator::::get(); - advance_to_block(intermediate_aggregator.limit_block + 1); - - // Check that circular buffer is updated as expected - let circular_buffer = ValuesCircularBuffer::::get(); - assert_eq!( - circular_buffer.buffer.len(), - circular_buffer_length as usize - ); - assert_eq!(circular_buffer.head, (x + 1) % circular_buffer_length); - } - }) -} diff --git a/pallets/price-aggregator/src/weights.rs b/pallets/price-aggregator/src/weights.rs deleted file mode 100644 index 9523e49f7..000000000 --- a/pallets/price-aggregator/src/weights.rs +++ /dev/null @@ -1,99 +0,0 @@ - -// This file is part of Astar. - -// Copyright (C) Stake Technologies Pte.Ltd. -// SPDX-License-Identifier: GPL-3.0-or-later - -// Astar is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. - -// Astar is distributed in the hope that it will be useful, -// 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. - -// You should have received a copy of the GNU General Public License -// along with Astar. If not, see . - -//! Autogenerated weights for pallet_price_aggregator -//! -//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev -//! DATE: 2024-03-18, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` -//! WORST CASE MAP SIZE: `1000000` -//! HOSTNAME: `gh-runner-01-ovh`, CPU: `Intel(R) Xeon(R) E-2236 CPU @ 3.40GHz` -//! EXECUTION: , WASM-EXECUTION: Compiled, CHAIN: Some("shibuya-dev"), DB CACHE: 1024 - -// Executed Command: -// ./target/release/astar-collator -// benchmark -// pallet -// --chain=shibuya-dev -// --steps=50 -// --repeat=20 -// --pallet=pallet_price_aggregator -// --extrinsic=* -// --execution=wasm -// --wasm-execution=compiled -// --heap-pages=4096 -// --output=./benchmark-results/shibuya-dev/price_aggregator_weights.rs -// --template=./scripts/templates/weight-template.hbs - -#![cfg_attr(rustfmt, rustfmt_skip)] -#![allow(unused_parens)] -#![allow(unused_imports)] - -use frame_support::{traits::Get, weights::{Weight, constants::RocksDbWeight}}; -use core::marker::PhantomData; - -/// Weight functions needed for pallet_price_aggregator. -pub trait WeightInfo { - fn process_block_aggregated_values() -> Weight; - fn process_intermediate_aggregated_values() -> Weight; -} - -/// Weights for pallet_price_aggregator using the Substrate node and recommended hardware. -pub struct SubstrateWeight(PhantomData); -impl WeightInfo for SubstrateWeight { - fn process_block_aggregated_values() -> Weight { - // Proof Size summary in bytes: - // Measured: `0` - // Estimated: `0` - // Minimum execution time: 3_417_000 picoseconds. - Weight::from_parts(3_520_000, 0) - } - /// Storage: `PriceAggregator::ValuesCircularBuffer` (r:1 w:1) - /// Proof: `PriceAggregator::ValuesCircularBuffer` (`max_values`: Some(1), `max_size`: Some(117), added: 612, mode: `MaxEncodedLen`) - fn process_intermediate_aggregated_values() -> Weight { - // Proof Size summary in bytes: - // Measured: `102` - // Estimated: `1602` - // Minimum execution time: 9_093_000 picoseconds. - Weight::from_parts(9_297_000, 1602) - .saturating_add(T::DbWeight::get().reads(1_u64)) - .saturating_add(T::DbWeight::get().writes(1_u64)) - } -} - -// For backwards compatibility and tests -impl WeightInfo for () { - fn process_block_aggregated_values() -> Weight { - // Proof Size summary in bytes: - // Measured: `0` - // Estimated: `0` - // Minimum execution time: 3_417_000 picoseconds. - Weight::from_parts(3_520_000, 0) - } - /// Storage: `PriceAggregator::ValuesCircularBuffer` (r:1 w:1) - /// Proof: `PriceAggregator::ValuesCircularBuffer` (`max_values`: Some(1), `max_size`: Some(117), added: 612, mode: `MaxEncodedLen`) - fn process_intermediate_aggregated_values() -> Weight { - // Proof Size summary in bytes: - // Measured: `102` - // Estimated: `1602` - // Minimum execution time: 9_093_000 picoseconds. - Weight::from_parts(9_297_000, 1602) - .saturating_add(RocksDbWeight::get().reads(1_u64)) - .saturating_add(RocksDbWeight::get().writes(1_u64)) - } -} diff --git a/pallets/static-price-provider/Cargo.toml b/pallets/static-price-provider/Cargo.toml deleted file mode 100644 index aa52851b6..000000000 --- a/pallets/static-price-provider/Cargo.toml +++ /dev/null @@ -1,64 +0,0 @@ -[package] -name = "pallet-static-price-provider" -version = "0.1.0" -license = "GPL-3.0-or-later" -description = "Static price provider for native currency" -authors.workspace = true -edition.workspace = true -homepage.workspace = true -repository.workspace = true - -[lints] -workspace = true - -[dependencies] -log = { workspace = true } -parity-scale-codec = { workspace = true } -serde = { workspace = true } - -astar-primitives = { workspace = true } -frame-support = { workspace = true } -frame-system = { workspace = true } -scale-info = { workspace = true } -sp-arithmetic = { workspace = true } -sp-runtime = { workspace = true } -sp-std = { workspace = true } - -frame-benchmarking = { workspace = true, optional = true } - -[dev-dependencies] -pallet-balances = { workspace = true } -sp-core = { workspace = true } -sp-io = { workspace = true } - -[features] -default = ["std"] -std = [ - "parity-scale-codec/std", - "log/std", - "sp-core/std", - "scale-info/std", - "serde/std", - "sp-std/std", - "frame-support/std", - "frame-system/std", - "pallet-balances/std", - "astar-primitives/std", - "sp-arithmetic/std", - "frame-benchmarking?/std", - "sp-runtime/std", -] -runtime-benchmarks = [ - "frame-benchmarking", - "frame-support/runtime-benchmarks", - "frame-system/runtime-benchmarks", - "sp-runtime/runtime-benchmarks", - "astar-primitives/runtime-benchmarks", - "frame-benchmarking/runtime-benchmarks", -] -try-runtime = [ - "frame-support/try-runtime", - "astar-primitives/try-runtime", - "frame-system/try-runtime", - "sp-runtime/try-runtime", -] diff --git a/pallets/static-price-provider/src/lib.rs b/pallets/static-price-provider/src/lib.rs deleted file mode 100644 index 5a9992621..000000000 --- a/pallets/static-price-provider/src/lib.rs +++ /dev/null @@ -1,112 +0,0 @@ -// This file is part of Astar. - -// Copyright (C) Stake Technologies Pte.Ltd. -// SPDX-License-Identifier: GPL-3.0-or-later - -// Astar is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. - -// Astar is distributed in the hope that it will be useful, -// 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. - -// You should have received a copy of the GNU General Public License -// along with Astar. If not, see . - -//! # Static Price Provider Pallet -//! -//! A simple pallet that provides a static price for the native currency. -//! This is a temporary solution before oracle is implemented & operational. -//! -//! ## Overview -//! -//! The Static Price Provider pallet provides functionality for setting the active native currency price via privileged call. -//! Only the root can set the price. -//! -//! Network maintainers must ensure to update the price at appropriate times so that inflation & dApp Staking rewards are calculated correctly. - -#![cfg_attr(not(feature = "std"), no_std)] - -use frame_support::pallet_prelude::*; -use frame_system::{ensure_root, pallet_prelude::*}; -pub use pallet::*; -use sp_arithmetic::{fixed_point::FixedU128, traits::Zero}; -use sp_std::marker::PhantomData; - -use astar_primitives::oracle::PriceProvider; - -#[cfg(test)] -mod mock; -#[cfg(test)] -mod tests; - -#[frame_support::pallet] -pub mod pallet { - - use super::*; - - /// The current storage version. - pub const STORAGE_VERSION: StorageVersion = StorageVersion::new(2); - - #[pallet::pallet] - #[pallet::storage_version(STORAGE_VERSION)] - pub struct Pallet(PhantomData); - - #[pallet::config] - pub trait Config: frame_system::Config {} - - #[pallet::event] - #[pallet::generate_deposit(pub(crate) fn deposit_event)] - pub enum Event { - /// New static native currency price has been set. - PriceSet { price: FixedU128 }, - } - - #[pallet::error] - pub enum Error { - /// Zero is invalid value for the price (hopefully). - ZeroPrice, - } - - /// Default value handler for active price. - /// This pallet is temporary and it's not worth bothering with genesis config. - pub struct DefaultActivePrice; - impl Get for DefaultActivePrice { - fn get() -> FixedU128 { - FixedU128::from_rational(1, 10) - } - } - - /// Current active native currency price. - #[pallet::storage] - #[pallet::whitelist_storage] - pub type ActivePrice = StorageValue<_, FixedU128, ValueQuery, DefaultActivePrice>; - - #[pallet::call] - impl Pallet { - /// Privileged action used to set the active native currency price. - /// - /// This is a temporary solution before oracle is implemented & operational. - #[pallet::call_index(0)] - #[pallet::weight(T::DbWeight::get().writes(1))] - pub fn force_set_price(origin: OriginFor, price: FixedU128) -> DispatchResult { - ensure_root(origin)?; - ensure!(!price.is_zero(), Error::::ZeroPrice); - - ActivePrice::::put(price); - - Self::deposit_event(Event::::PriceSet { price }); - - Ok(().into()) - } - } - - impl PriceProvider for Pallet { - fn average_price() -> FixedU128 { - ActivePrice::::get() - } - } -} diff --git a/pallets/static-price-provider/src/mock.rs b/pallets/static-price-provider/src/mock.rs deleted file mode 100644 index dc95c9d31..000000000 --- a/pallets/static-price-provider/src/mock.rs +++ /dev/null @@ -1,74 +0,0 @@ -// This file is part of Astar. - -// Copyright (C) Stake Technologies Pte.Ltd. -// SPDX-License-Identifier: GPL-3.0-or-later - -// Astar is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. - -// Astar is distributed in the hope that it will be useful, -// 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. - -// You should have received a copy of the GNU General Public License -// along with Astar. If not, see . - -use crate::{self as pallet_static_price_provider}; - -use frame_support::{ - construct_runtime, derive_impl, parameter_types, traits::ConstU128, weights::Weight, -}; -use sp_io::TestExternalities; -use sp_runtime::BuildStorage; - -use astar_primitives::{Balance, BlockNumber}; - -type Block = frame_system::mocking::MockBlock; - -parameter_types! { - pub const BlockHashCount: BlockNumber = 250; - pub BlockWeights: frame_system::limits::BlockWeights = - frame_system::limits::BlockWeights::simple_max(Weight::from_parts(1024, 0)); -} - -#[derive_impl(frame_system::config_preludes::TestDefaultConfig)] -impl frame_system::Config for Test { - type Block = Block; - type AccountData = pallet_balances::AccountData; -} - -#[derive_impl(pallet_balances::config_preludes::TestDefaultConfig)] -impl pallet_balances::Config for Test { - type Balance = Balance; - type ExistentialDeposit = ConstU128<1>; - type AccountStore = System; -} - -impl pallet_static_price_provider::Config for Test {} - -construct_runtime!( - pub struct Test { - System: frame_system, - Balances: pallet_balances, - StaticPriceProvider: pallet_static_price_provider, - } -); - -pub struct ExternalityBuilder; -impl ExternalityBuilder { - pub fn build() -> TestExternalities { - let storage = frame_system::GenesisConfig::::default() - .build_storage() - .unwrap(); - - let mut ext = TestExternalities::from(storage); - ext.execute_with(|| { - System::set_block_number(1); - }); - - ext - } -} diff --git a/pallets/static-price-provider/src/tests.rs b/pallets/static-price-provider/src/tests.rs deleted file mode 100644 index 55c7b0e00..000000000 --- a/pallets/static-price-provider/src/tests.rs +++ /dev/null @@ -1,60 +0,0 @@ -// This file is part of Astar. - -// Copyright (C) Stake Technologies Pte.Ltd. -// SPDX-License-Identifier: GPL-3.0-or-later - -// Astar is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. - -// Astar is distributed in the hope that it will be useful, -// 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. - -// You should have received a copy of the GNU General Public License -// along with Astar. If not, see . - -use super::{pallet::Error, Event, *}; -use frame_support::{assert_noop, assert_ok}; -use mock::*; -use sp_runtime::traits::{BadOrigin, Zero}; - -#[test] -fn force_set_price_works() { - ExternalityBuilder::build().execute_with(|| { - assert!(!ActivePrice::::get().is_zero(), "Sanity check"); - - let new_price = ActivePrice::::get() * 2.into(); - assert_ok!(StaticPriceProvider::force_set_price( - RuntimeOrigin::root(), - new_price - )); - System::assert_last_event(RuntimeEvent::StaticPriceProvider(Event::PriceSet { - price: new_price, - })); - assert_eq!(ActivePrice::::get(), new_price); - assert_eq!(StaticPriceProvider::average_price(), new_price); - }) -} - -#[test] -fn force_set_zero_price_fails() { - ExternalityBuilder::build().execute_with(|| { - assert_noop!( - StaticPriceProvider::force_set_price(RuntimeOrigin::root(), 0.into()), - Error::::ZeroPrice - ); - }) -} - -#[test] -fn force_set_price_with_invalid_origin_fails() { - ExternalityBuilder::build().execute_with(|| { - assert_noop!( - StaticPriceProvider::force_set_price(RuntimeOrigin::signed(1), 1.into()), - BadOrigin - ); - }) -} diff --git a/precompiles/dapp-staking/src/test/mock.rs b/precompiles/dapp-staking/src/test/mock.rs index 4fee881e2..09f9c6e93 100644 --- a/precompiles/dapp-staking/src/test/mock.rs +++ b/precompiles/dapp-staking/src/test/mock.rs @@ -43,7 +43,6 @@ extern crate alloc; use astar_primitives::{ dapp_staking::{ CycleConfiguration, EraNumber, PeriodNumber, SmartContract, StakingRewardHandler, - FIXED_TIER_SLOTS_ARGS, }, AccountId, Balance, BlockNumber, }; @@ -227,7 +226,6 @@ impl pallet_dapp_staking::Config for Test { type EraRewardSpanLength = ConstU32<8>; type RewardRetentionInPeriods = ConstU32<2>; type MaxNumberOfContracts = ConstU32<10>; - type MaxNumberOfContractsLegacy = ConstU32<10>; type MaxUnlockingChunks = ConstU32<5>; type MinimumLockedAmount = ConstU128<10>; type UnlockingPeriod = ConstU32<2>; @@ -286,7 +284,6 @@ impl ExternalityBuilder { required_percentage: Perbill::from_percent(1), }, ], - slot_number_args: FIXED_TIER_SLOTS_ARGS, slots_per_tier: vec![10, 20, 30, 40], safeguard: None, tier_rank_multipliers: vec![10_000u32, 20_000, 20_000, 20_000], diff --git a/primitives/Cargo.toml b/primitives/Cargo.toml index 2735d3843..4c07ee193 100644 --- a/primitives/Cargo.toml +++ b/primitives/Cargo.toml @@ -40,7 +40,6 @@ xcm-builder = { workspace = true } xcm-executor = { workspace = true } # ORML dependencies -orml-oracle = { workspace = true } orml-traits = { workspace = true } pallet-contracts = { workspace = true } @@ -77,7 +76,6 @@ std = [ "xcm/std", "xcm-builder/std", "xcm-executor/std", - "orml-oracle/std", "orml-traits/std", "pallet-xc-asset-config/std", "fp-evm/std", @@ -102,14 +100,12 @@ runtime-benchmarks = [ "pallet-collective/runtime-benchmarks", "pallet-membership/runtime-benchmarks", "pallet-treasury/runtime-benchmarks", - "orml-oracle/runtime-benchmarks", "xcm/runtime-benchmarks", ] try-runtime = [ "pallet-contracts/try-runtime", "frame-support/try-runtime", "frame-system/try-runtime", - "orml-oracle/try-runtime", "pallet-assets/try-runtime", "pallet-evm/try-runtime", "pallet-xc-asset-config/try-runtime", diff --git a/primitives/src/dapp_staking.rs b/primitives/src/dapp_staking.rs index 694c0c1e1..f0418d4b3 100644 --- a/primitives/src/dapp_staking.rs +++ b/primitives/src/dapp_staking.rs @@ -184,10 +184,6 @@ impl AccountCheck for () { /// Fixed number of tier slots used by dApp-staking recalculation. pub const FIXED_NUMBER_OF_TIER_SLOTS: u16 = 16; -/// Standard tier slots arguments. -/// Decided for Astar, during the Tokenomics 3.0 revamp. -pub const FIXED_TIER_SLOTS_ARGS: (u64, u64) = (0, FIXED_NUMBER_OF_TIER_SLOTS as u64); - /// RankedTier is wrapper around u8 to hold both tier and rank. u8 has 2 bytes (8bits) and they're using in this order `0xrank_tier`. /// First 4 bits are used to hold rank and second 4 bits are used to hold tier. /// i.e: 0xa1 will hold rank: 10 and tier: 1 (0xa1 & 0xf == 1; 0xa1 >> 4 == 10;) diff --git a/primitives/src/governance.rs b/primitives/src/governance.rs index 10b38f286..f65b3e8a9 100644 --- a/primitives/src/governance.rs +++ b/primitives/src/governance.rs @@ -20,12 +20,11 @@ use crate::AccountId; use frame_support::traits::EitherOfDiverse; use frame_system::EnsureRoot; -pub type OracleMembershipInst = pallet_membership::Instance1; pub type MainCouncilMembershipInst = pallet_membership::Instance2; pub type TechnicalCommitteeMembershipInst = pallet_membership::Instance3; pub type CommunityCouncilMembershipInst = pallet_membership::Instance4; -// Leaving instance 1 for potentially having an oracle membership collective instance +// Instance 1 was previously used for OracleMembership (now removed) pub type MainCouncilCollectiveInst = pallet_collective::Instance2; pub type TechnicalCommitteeCollectiveInst = pallet_collective::Instance3; pub type CommunityCouncilCollectiveInst = pallet_collective::Instance4; diff --git a/primitives/src/lib.rs b/primitives/src/lib.rs index f4caab74c..81dde7d26 100644 --- a/primitives/src/lib.rs +++ b/primitives/src/lib.rs @@ -38,9 +38,6 @@ pub mod dapp_staking; /// Useful primitives for testing. pub mod testing; -/// Oracle & price primitives. -pub mod oracle; - /// Governance primitives. pub mod governance; diff --git a/primitives/src/oracle.rs b/primitives/src/oracle.rs deleted file mode 100644 index bc68b2377..000000000 --- a/primitives/src/oracle.rs +++ /dev/null @@ -1,64 +0,0 @@ -// This file is part of Astar. - -// Copyright (C) Stake Technologies Pte.Ltd. -// SPDX-License-Identifier: GPL-3.0-or-later - -// Astar is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. - -// Astar is distributed in the hope that it will be useful, -// 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. - -// You should have received a copy of the GNU General Public License -// along with Astar. If not, see . - -use frame_support::{pallet_prelude::*, traits::Time}; -use sp_arithmetic::fixed_point::FixedU128; -use sp_std::vec::Vec; - -/// Interface for fetching price of the native token. -pub trait PriceProvider { - /// Get the price of the native token. - fn average_price() -> Price; -} - -pub type Price = FixedU128; -pub type CurrencyAmount = FixedU128; - -#[derive( - Encode, - Decode, - DecodeWithMemTracking, - MaxEncodedLen, - Clone, - Copy, - Debug, - PartialEq, - Eq, - TypeInfo, -)] -pub enum CurrencyId { - ASTR, - SDN, -} - -type TimestampedValue = - orml_oracle::TimestampedValue>::Time as Time>::Moment>; - -/// A dummy implementation of `CombineData` trait that does nothing. -pub struct DummyCombineData(PhantomData<(T, I)>); -impl, I> orml_traits::CombineData> - for DummyCombineData -{ - fn combine_data( - _key: &CurrencyId, - _values: Vec>, - _prev_value: Option>, - ) -> Option> { - None - } -} diff --git a/runtime/astar/Cargo.toml b/runtime/astar/Cargo.toml index e4edf2b28..c51a006f6 100644 --- a/runtime/astar/Cargo.toml +++ b/runtime/astar/Cargo.toml @@ -106,7 +106,6 @@ xcm-executor = { workspace = true } xcm-runtime-apis = { workspace = true } # orml dependencies -orml-oracle = { workspace = true } orml-xcm-support = { workspace = true } orml-xtokens = { workspace = true } @@ -131,7 +130,6 @@ pallet-evm-precompile-sr25519 = { workspace = true } pallet-evm-precompile-substrate-ecdsa = { workspace = true } pallet-evm-precompile-xcm = { workspace = true } pallet-inflation = { workspace = true } -pallet-price-aggregator = { workspace = true } pallet-xc-asset-config = { workspace = true } pallet-xcm = { workspace = true } @@ -180,7 +178,6 @@ std = [ "moonbeam-rpc-primitives-debug/std", "moonbeam-rpc-primitives-txpool/std", "num_enum/std", - "orml-oracle/std", "orml-xcm-support/std", "orml-xtokens/std", "pallet-assets/std", @@ -217,7 +214,6 @@ std = [ "pallet-migrations/std", "pallet-multisig/std", "pallet-preimage/std", - "pallet-price-aggregator/std", "pallet-proxy/std", "pallet-scheduler/std", "pallet-session/std", @@ -275,7 +271,6 @@ runtime-benchmarks = [ "frame-support/runtime-benchmarks", "frame-system-benchmarking/runtime-benchmarks", "frame-system/runtime-benchmarks", - "orml-oracle/runtime-benchmarks", "orml-xtokens/runtime-benchmarks", "pallet-assets/runtime-benchmarks", "pallet-balances/runtime-benchmarks", @@ -301,7 +296,6 @@ runtime-benchmarks = [ "pallet-migrations/runtime-benchmarks", "pallet-multisig/runtime-benchmarks", "pallet-preimage/runtime-benchmarks", - "pallet-price-aggregator/runtime-benchmarks", "pallet-proxy/runtime-benchmarks", "pallet-scheduler/runtime-benchmarks", "pallet-sudo/runtime-benchmarks", @@ -336,7 +330,6 @@ try-runtime = [ "frame-system/try-runtime", "frame-try-runtime/try-runtime", "log", - "orml-oracle/try-runtime", "orml-xtokens/try-runtime", "pallet-assets/try-runtime", "pallet-aura/try-runtime", @@ -361,7 +354,6 @@ try-runtime = [ "pallet-migrations/try-runtime", "pallet-multisig/try-runtime", "pallet-preimage/try-runtime", - "pallet-price-aggregator/try-runtime", "pallet-proxy/try-runtime", "pallet-scheduler/try-runtime", "pallet-session/try-runtime", diff --git a/runtime/astar/src/genesis_config.rs b/runtime/astar/src/genesis_config.rs index 1476e1375..512f103ac 100644 --- a/runtime/astar/src/genesis_config.rs +++ b/runtime/astar/src/genesis_config.rs @@ -18,7 +18,7 @@ use crate::*; use astar_primitives::{ - dapp_staking::FIXED_TIER_SLOTS_ARGS, evm::EVM_REVERT_CODE, genesis::GenesisAccount, + evm::EVM_REVERT_CODE, genesis::GenesisAccount, parachain::ASTAR_ID, }; @@ -159,23 +159,12 @@ pub fn default_config(para_id: u32) -> serde_json::Value { }, ], slots_per_tier, - slot_number_args: FIXED_TIER_SLOTS_ARGS, safeguard: Some(false), tier_rank_multipliers, ..Default::default() }, inflation: Default::default(), - oracle_membership: OracleMembershipConfig { - members: vec![alice.account_id(), bob.account_id()] - .try_into() - .expect("Assumption is that at least two members will be allowed."), - ..Default::default() - }, - price_aggregator: PriceAggregatorConfig { - circular_buffer: vec![CurrencyAmount::from_rational(5, 10)] - .try_into() - .expect("Must work since buffer should have at least a single value."), - }, + council_membership: CouncilMembershipConfig { members: accounts .clone() diff --git a/runtime/astar/src/lib.rs b/runtime/astar/src/lib.rs index 54f2b4023..7ff340aca 100644 --- a/runtime/astar/src/lib.rs +++ b/runtime/astar/src/lib.rs @@ -98,9 +98,8 @@ use astar_primitives::{ EnsureRootOrThreeFourthMainCouncil, EnsureRootOrTwoThirdsCommunityCouncil, EnsureRootOrTwoThirdsMainCouncil, EnsureRootOrTwoThirdsTechnicalCommittee, MainCouncilCollectiveInst, MainCouncilMembershipInst, MainTreasuryInst, - OracleMembershipInst, TechnicalCommitteeCollectiveInst, TechnicalCommitteeMembershipInst, + TechnicalCommitteeCollectiveInst, TechnicalCommitteeMembershipInst, }, - oracle::{CurrencyAmount, CurrencyId, DummyCombineData, Price}, xcm::AssetLocationIdConverter, Address, AssetId, BlockNumber, Hash, Header, Nonce, UnfreezeChainOnFailedMigration, }; @@ -468,7 +467,6 @@ impl pallet_dapp_staking::Config for Runtime { type EraRewardSpanLength = ConstU32<16>; type RewardRetentionInPeriods = ConstU32<4>; type MaxNumberOfContracts = ConstU32<{ FIXED_NUMBER_OF_TIER_SLOTS as u32 }>; - type MaxNumberOfContractsLegacy = ConstU32<500>; type MaxUnlockingChunks = ConstU32<8>; type MinimumLockedAmount = MinimumStakingAmount; type UnlockingPeriod = ConstU32<9>; @@ -1190,94 +1188,6 @@ impl pallet_proxy::Config for Runtime { type AnnouncementDepositFactor = AnnouncementDepositFactor; } -parameter_types! { - pub const NativeCurrencyId: CurrencyId = CurrencyId::ASTR; - // Aggregate values for one day. - pub const AggregationDuration: BlockNumber = DAYS; -} - -impl pallet_price_aggregator::Config for Runtime { - type MaxValuesPerBlock = ConstU32<8>; - type ProcessBlockValues = pallet_price_aggregator::MedianBlockValue; - type NativeCurrencyId = NativeCurrencyId; - // 7 days - type CircularBufferLength = ConstU32<7>; - type AggregationDuration = AggregationDuration; - type WeightInfo = pallet_price_aggregator::weights::SubstrateWeight; -} - -#[cfg(feature = "runtime-benchmarks")] -pub struct OracleBenchmarkHelper; -#[cfg(feature = "runtime-benchmarks")] -impl orml_oracle::BenchmarkHelper> for OracleBenchmarkHelper { - fn get_currency_id_value_pairs() -> sp_runtime::BoundedVec<(CurrencyId, Price), ConstU32<2>> { - sp_runtime::BoundedVec::try_from(vec![ - (CurrencyId::ASTR, Price::from_rational(15, 100)), - (CurrencyId::ASTR, Price::from_rational(15, 100)), - ]) - .expect("out of bounds") - } -} - -parameter_types! { - // Cannot specify `Root` so need to do it like this, unfortunately. - pub RootOperatorAccountId: AccountId = AccountId::from([0xffu8; 32]); -} - -impl orml_oracle::Config for Runtime { - type OnNewData = PriceAggregator; - type CombineData = DummyCombineData; - type Time = Timestamp; - type OracleKey = CurrencyId; - type OracleValue = Price; - type RootOperatorAccountId = RootOperatorAccountId; - #[cfg(feature = "runtime-benchmarks")] - type Members = OracleMembershipWrapper; - #[cfg(not(feature = "runtime-benchmarks"))] - type Members = OracleMembership; - type MaxHasDispatchedSize = ConstU32<8>; - type WeightInfo = weights::orml_oracle::SubstrateWeight; - #[cfg(feature = "runtime-benchmarks")] - type MaxFeedValues = ConstU32<2>; - #[cfg(not(feature = "runtime-benchmarks"))] - type MaxFeedValues = ConstU32<1>; - #[cfg(feature = "runtime-benchmarks")] - type BenchmarkHelper = OracleBenchmarkHelper; -} - -impl pallet_membership::Config for Runtime { - type RuntimeEvent = RuntimeEvent; - type AddOrigin = EnsureRoot; - type RemoveOrigin = EnsureRoot; - type SwapOrigin = EnsureRoot; - type ResetOrigin = EnsureRoot; - type PrimeOrigin = EnsureRoot; - - type MembershipInitialized = (); - type MembershipChanged = (); - type MaxMembers = ConstU32<16>; - type WeightInfo = pallet_membership::weights::SubstrateWeight; -} - -/// OracleMembership wrapper used by benchmarks -#[cfg(feature = "runtime-benchmarks")] -pub struct OracleMembershipWrapper; - -#[cfg(feature = "runtime-benchmarks")] -impl frame_support::traits::SortedMembers for OracleMembershipWrapper { - fn sorted_members() -> Vec { - OracleMembership::sorted_members() - } - - fn add(account: &AccountId) { - use alloc::borrow::ToOwned; - frame_support::assert_ok!(OracleMembership::add_member( - frame_system::RawOrigin::Root.into(), - account.to_owned().into() - )); - } -} - parameter_types! { pub const CouncilMaxMembers: u32 = 16; pub const TechnicalCommitteeMaxMembers: u32 = 8; @@ -1549,7 +1459,6 @@ impl Contains for SafeModeWhitelistedCalls { | RuntimeCall::Proxy(_) | RuntimeCall::Multisig(_) | RuntimeCall::Preimage(_) - | RuntimeCall::Oracle(_) | RuntimeCall::Utility(_) | RuntimeCall::TxPause(_) | RuntimeCall::SafeMode(_) => true, @@ -1674,13 +1583,8 @@ mod runtime { pub type DappStaking = pallet_dapp_staking; #[runtime::pallet_index(36)] pub type Assets = pallet_assets; - #[runtime::pallet_index(37)] - pub type PriceAggregator = pallet_price_aggregator; - #[runtime::pallet_index(38)] - pub type Oracle = orml_oracle; - #[runtime::pallet_index(39)] - pub type OracleMembership = pallet_membership; - + // skip 37 - price_aggregator previously + // skip 38/39 - oracle and oracle_membership previously // Collator support #[runtime::pallet_index(40)] pub type Authorship = pallet_authorship; @@ -1790,6 +1694,12 @@ pub type Executive = frame_executive::Executive< Migrations, >; +parameter_types! { + pub const PriceAggregatorPalletStr: &'static str = "PriceAggregator"; + pub const OraclePalletStr: &'static str = "Oracle"; + pub const OracleMembershipPalletStr: &'static str = "OracleMembership"; +} + /// All migrations that will run on the next runtime upgrade. /// /// __NOTE:__ THE ORDER IS IMPORTANT. @@ -1797,12 +1707,10 @@ pub type Migrations = (Unreleased, Permanent); /// Unreleased migrations. Add new ones here: pub type Unreleased = ( - pallet_dapp_staking::migration::versioned_migrations::V10ToV11< - Runtime, - pallet_dapp_staking::migration::DefaultTierParamsV11, - ConstU32<11>, - ConstU32<111>, - >, + pallet_dapp_staking::migration::versioned_migrations::V11ToV12, + frame_support::migrations::RemovePallet, + frame_support::migrations::RemovePallet, + frame_support::migrations::RemovePallet, ); /// Migrations/checks that do not need to be versioned and can run on every upgrade. @@ -1890,7 +1798,6 @@ mod benches { [pallet_dynamic_evm_base_fee, DynamicEvmBaseFee] [xcm_benchmarks_generic, XcmGeneric] [xcm_benchmarks_fungible, XcmFungible] - [orml_oracle, Oracle] [pallet_tx_pause, TxPause] [pallet_safe_mode, SafeMode] ); diff --git a/runtime/astar/src/weights/mod.rs b/runtime/astar/src/weights/mod.rs index ad38a00ae..f6f719f17 100644 --- a/runtime/astar/src/weights/mod.rs +++ b/runtime/astar/src/weights/mod.rs @@ -20,7 +20,6 @@ mod block_weights; mod extrinsic_weights; pub mod frame_system_extensions; -pub mod orml_oracle; pub mod pallet_assets; pub mod pallet_dapp_staking; pub mod pallet_inflation; diff --git a/runtime/astar/src/weights/orml_oracle.rs b/runtime/astar/src/weights/orml_oracle.rs deleted file mode 100644 index 6ddbba78d..000000000 --- a/runtime/astar/src/weights/orml_oracle.rs +++ /dev/null @@ -1,91 +0,0 @@ - -// This file is part of Astar. - -// Copyright (C) Stake Technologies Pte.Ltd. -// SPDX-License-Identifier: GPL-3.0-or-later - -// Astar is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. - -// Astar is distributed in the hope that it will be useful, -// 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. - -// You should have received a copy of the GNU General Public License -// along with Astar. If not, see . - -//! Autogenerated weights for `orml_oracle` -//! -//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 32.0.0 -//! DATE: 2025-12-19, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` -//! WORST CASE MAP SIZE: `1000000` -//! HOSTNAME: `gh-runner-01-ovh`, CPU: `Intel(R) Xeon(R) E-2236 CPU @ 3.40GHz` -//! WASM-EXECUTION: `Compiled`, CHAIN: `None`, DB CACHE: 1024 - -// Executed Command: -// frame-omni-bencher -// v1 -// benchmark -// pallet -// --runtime=./target/release/wbuild/astar-runtime/astar_runtime.compact.compressed.wasm -// --steps=50 -// --repeat=20 -// --pallet=orml_oracle -// --extrinsic=* -// --wasm-execution=compiled -// --heap-pages=4096 -// --output=./benchmark-results/astar/runtime/oracle_weights.rs -// --template=./scripts/templates/runtime-weight-template.hbs - -#![cfg_attr(rustfmt, rustfmt_skip)] -#![allow(unused_parens)] -#![allow(unused_imports)] -#![allow(missing_docs)] -#![allow(dead_code)] - -use frame_support::{traits::Get, weights::Weight}; -use core::marker::PhantomData; - -/// Weight functions for `orml_oracle`. -pub struct SubstrateWeight(PhantomData); -impl orml_oracle::WeightInfo for SubstrateWeight { - /// Storage: `OracleMembership::Members` (r:1 w:0) - /// Proof: `OracleMembership::Members` (`max_values`: Some(1), `max_size`: Some(513), added: 1008, mode: `MaxEncodedLen`) - /// Storage: `Oracle::HasDispatched` (r:1 w:1) - /// Proof: `Oracle::HasDispatched` (`max_values`: Some(1), `max_size`: Some(257), added: 752, mode: `MaxEncodedLen`) - /// Storage: `Timestamp::Now` (r:1 w:0) - /// Proof: `Timestamp::Now` (`max_values`: Some(1), `max_size`: Some(8), added: 503, mode: `MaxEncodedLen`) - /// Storage: `Oracle::RawValues` (r:3 w:1) - /// Proof: `Oracle::RawValues` (`max_values`: None, `max_size`: Some(73), added: 2548, mode: `MaxEncodedLen`) - /// Storage: `Oracle::Values` (r:1 w:0) - /// Proof: `Oracle::Values` (`max_values`: None, `max_size`: Some(33), added: 2508, mode: `MaxEncodedLen`) - /// The range of component `x` is `[0, 2]`. - fn feed_values(x: u32, ) -> Weight { - // Proof Size summary in bytes: - // Measured: `346` - // Estimated: `8634` - // Minimum execution time: 17_383_000 picoseconds. - Weight::from_parts(18_245_764, 0) - .saturating_add(Weight::from_parts(0, 8634)) - // Standard Error: 62_942 - .saturating_add(Weight::from_parts(16_419_329, 0).saturating_mul(x.into())) - .saturating_add(T::DbWeight::get().reads(3)) - .saturating_add(T::DbWeight::get().reads((4_u64).saturating_mul(x.into()))) - .saturating_add(T::DbWeight::get().writes(1)) - .saturating_add(T::DbWeight::get().writes((1_u64).saturating_mul(x.into()))) - } - /// Storage: `Oracle::HasDispatched` (r:0 w:1) - /// Proof: `Oracle::HasDispatched` (`max_values`: Some(1), `max_size`: Some(257), added: 752, mode: `MaxEncodedLen`) - fn on_finalize() -> Weight { - // Proof Size summary in bytes: - // Measured: `0` - // Estimated: `0` - // Minimum execution time: 2_114_000 picoseconds. - Weight::from_parts(2_509_000, 0) - .saturating_add(Weight::from_parts(0, 0)) - .saturating_add(T::DbWeight::get().writes(1)) - } -} diff --git a/runtime/shibuya/Cargo.toml b/runtime/shibuya/Cargo.toml index d3692a2c4..3d73fc139 100644 --- a/runtime/shibuya/Cargo.toml +++ b/runtime/shibuya/Cargo.toml @@ -106,7 +106,6 @@ xcm-executor = { workspace = true } xcm-runtime-apis = { workspace = true } # orml dependencies -orml-oracle = { workspace = true } orml-xcm-support = { workspace = true } orml-xtokens = { workspace = true } @@ -127,7 +126,6 @@ pallet-evm-precompile-substrate-ecdsa = { workspace = true } pallet-evm-precompile-unified-accounts = { workspace = true } pallet-evm-precompile-xcm = { workspace = true } pallet-inflation = { workspace = true } -pallet-price-aggregator = { workspace = true } pallet-unified-accounts = { workspace = true } pallet-xc-asset-config = { workspace = true } pallet-xcm = { workspace = true } @@ -185,7 +183,6 @@ std = [ "moonbeam-rpc-primitives-debug/std", "moonbeam-rpc-primitives-txpool/std", "num_enum/std", - "orml-oracle/std", "orml-xcm-support/std", "orml-xtokens/std", "pallet-assets/std", @@ -227,7 +224,6 @@ std = [ "pallet-migrations/std", "pallet-multisig/std", "pallet-preimage/std", - "pallet-price-aggregator/std", "pallet-proxy/std", "pallet-safe-mode/std", "pallet-scheduler/std", @@ -288,7 +284,6 @@ runtime-benchmarks = [ "frame-support/runtime-benchmarks", "frame-system-benchmarking/runtime-benchmarks", "frame-system/runtime-benchmarks", - "orml-oracle/runtime-benchmarks", "orml-xtokens/runtime-benchmarks", "pallet-assets/runtime-benchmarks", "pallet-balances/runtime-benchmarks", @@ -313,7 +308,6 @@ runtime-benchmarks = [ "pallet-migrations/runtime-benchmarks", "pallet-multisig/runtime-benchmarks", "pallet-preimage/runtime-benchmarks", - "pallet-price-aggregator/runtime-benchmarks", "pallet-proxy/runtime-benchmarks", "pallet-safe-mode/runtime-benchmarks", "pallet-scheduler/runtime-benchmarks", @@ -351,7 +345,6 @@ try-runtime = [ "frame-system/try-runtime", "frame-try-runtime/try-runtime", "log", - "orml-oracle/try-runtime", "orml-xtokens/try-runtime", "pallet-assets/try-runtime", "pallet-aura/try-runtime", @@ -377,7 +370,6 @@ try-runtime = [ "pallet-migrations/try-runtime", "pallet-multisig/try-runtime", "pallet-preimage/try-runtime", - "pallet-price-aggregator/try-runtime", "pallet-proxy/try-runtime", "pallet-safe-mode/try-runtime", "pallet-scheduler/try-runtime", diff --git a/runtime/shibuya/src/genesis_config.rs b/runtime/shibuya/src/genesis_config.rs index 277735ea9..abb6906c5 100644 --- a/runtime/shibuya/src/genesis_config.rs +++ b/runtime/shibuya/src/genesis_config.rs @@ -18,7 +18,7 @@ use crate::*; use astar_primitives::{ - dapp_staking::FIXED_TIER_SLOTS_ARGS, evm::EVM_REVERT_CODE, genesis::GenesisAccount, + evm::EVM_REVERT_CODE, genesis::GenesisAccount, parachain::SHIBUYA_ID, }; use sp_core::crypto::Ss58Codec; @@ -171,23 +171,12 @@ pub fn default_config(para_id: u32) -> serde_json::Value { }, ], slots_per_tier, - slot_number_args: FIXED_TIER_SLOTS_ARGS, safeguard: Some(false), tier_rank_multipliers, ..Default::default() }, inflation: Default::default(), - oracle_membership: OracleMembershipConfig { - members: vec![alice.account_id(), bob.account_id()] - .try_into() - .expect("Assumption is that at least two members will be allowed."), - ..Default::default() - }, - price_aggregator: PriceAggregatorConfig { - circular_buffer: vec![CurrencyAmount::from_rational(5, 10)] - .try_into() - .expect("Must work since buffer should have at least a single value."), - }, + council_membership: CouncilMembershipConfig { members: accounts .clone() diff --git a/runtime/shibuya/src/lib.rs b/runtime/shibuya/src/lib.rs index 4dd578ad4..69e2c24c6 100644 --- a/runtime/shibuya/src/lib.rs +++ b/runtime/shibuya/src/lib.rs @@ -94,10 +94,9 @@ use astar_primitives::{ EnsureRootOrHalfMainCouncil, EnsureRootOrHalfTechCommitteeOrTwoThirdCouncil, EnsureRootOrHalfTechnicalCommittee, EnsureRootOrThreeFourthMainCouncil, EnsureRootOrTwoThirdsMainCouncil, MainCouncilCollectiveInst, MainCouncilMembershipInst, - MainTreasuryInst, OracleMembershipInst, TechnicalCommitteeCollectiveInst, + MainTreasuryInst, TechnicalCommitteeCollectiveInst, TechnicalCommitteeMembershipInst, }, - oracle::{CurrencyAmount, CurrencyId, DummyCombineData, Price}, xcm::AssetLocationIdConverter, Address, AssetId, BlockNumber, Hash, Header, Nonce, UnfreezeChainOnFailedMigration, }; @@ -493,7 +492,6 @@ impl pallet_dapp_staking::Config for Runtime { type EraRewardSpanLength = ConstU32<16>; type RewardRetentionInPeriods = ConstU32<2>; type MaxNumberOfContracts = ConstU32<{ FIXED_NUMBER_OF_TIER_SLOTS as u32 }>; - type MaxNumberOfContractsLegacy = ConstU32<500>; type MaxUnlockingChunks = ConstU32<8>; type MinimumLockedAmount = MinimumStakingAmount; type UnlockingPeriod = ConstU32<4>; @@ -1216,94 +1214,6 @@ impl pallet_unified_accounts::Config for Runtime { type WeightInfo = pallet_unified_accounts::weights::SubstrateWeight; } -parameter_types! { - // Of course it's not true for Shibuya, but SBY is worthless, a test token. - pub const NativeCurrencyId: CurrencyId = CurrencyId::ASTR; - // Aggregate values for one day. - pub const AggregationDuration: BlockNumber = DAYS; -} - -impl pallet_price_aggregator::Config for Runtime { - type MaxValuesPerBlock = ConstU32<8>; - type ProcessBlockValues = pallet_price_aggregator::MedianBlockValue; - type NativeCurrencyId = NativeCurrencyId; - // 7 days - type CircularBufferLength = ConstU32<7>; - type AggregationDuration = AggregationDuration; - type WeightInfo = pallet_price_aggregator::weights::SubstrateWeight; -} - -#[cfg(feature = "runtime-benchmarks")] -pub struct OracleBenchmarkHelper; -#[cfg(feature = "runtime-benchmarks")] -impl orml_oracle::BenchmarkHelper> for OracleBenchmarkHelper { - fn get_currency_id_value_pairs() -> sp_runtime::BoundedVec<(CurrencyId, Price), ConstU32<2>> { - sp_runtime::BoundedVec::try_from(vec![ - (CurrencyId::ASTR, Price::from_rational(15, 100)), - (CurrencyId::ASTR, Price::from_rational(15, 100)), - ]) - .expect("out of bounds") - } -} - -parameter_types! { - // Cannot specify `Root` so need to do it like this, unfortunately. - pub RootOperatorAccountId: AccountId = AccountId::from([0xffu8; 32]); -} - -impl orml_oracle::Config for Runtime { - type OnNewData = PriceAggregator; - type CombineData = DummyCombineData; - type Time = Timestamp; - type OracleKey = CurrencyId; - type OracleValue = Price; - type RootOperatorAccountId = RootOperatorAccountId; - #[cfg(feature = "runtime-benchmarks")] - type Members = OracleMembershipWrapper; - #[cfg(not(feature = "runtime-benchmarks"))] - type Members = OracleMembership; - type MaxHasDispatchedSize = ConstU32<8>; - type WeightInfo = weights::orml_oracle::SubstrateWeight; - #[cfg(feature = "runtime-benchmarks")] - type MaxFeedValues = ConstU32<2>; - #[cfg(not(feature = "runtime-benchmarks"))] - type MaxFeedValues = ConstU32<1>; - #[cfg(feature = "runtime-benchmarks")] - type BenchmarkHelper = OracleBenchmarkHelper; -} - -impl pallet_membership::Config for Runtime { - type RuntimeEvent = RuntimeEvent; - type AddOrigin = EnsureRootOrHalfMainCouncil; - type RemoveOrigin = EnsureRootOrHalfMainCouncil; - type SwapOrigin = EnsureRootOrHalfMainCouncil; - type ResetOrigin = EnsureRootOrHalfMainCouncil; - type PrimeOrigin = EnsureRootOrHalfMainCouncil; - type MembershipInitialized = (); - type MembershipChanged = (); - type MaxMembers = ConstU32<16>; - type WeightInfo = pallet_membership::weights::SubstrateWeight; -} - -/// OracleMembership wrapper used by benchmarks -#[cfg(feature = "runtime-benchmarks")] -pub struct OracleMembershipWrapper; - -#[cfg(feature = "runtime-benchmarks")] -impl frame_support::traits::SortedMembers for OracleMembershipWrapper { - fn sorted_members() -> Vec { - OracleMembership::sorted_members() - } - - fn add(account: &AccountId) { - use alloc::borrow::ToOwned; - frame_support::assert_ok!(OracleMembership::add_member( - frame_system::RawOrigin::Root.into(), - account.to_owned().into() - )); - } -} - parameter_types! { pub const CouncilMaxMembers: u32 = 16; pub const TechnicalCommitteeMaxMembers: u32 = 8; @@ -1575,7 +1485,6 @@ impl Contains for SafeModeWhitelistedCalls { | RuntimeCall::Proxy(_) | RuntimeCall::Multisig(_) | RuntimeCall::Preimage(_) - | RuntimeCall::Oracle(_) | RuntimeCall::Utility(_) | RuntimeCall::TxPause(_) | RuntimeCall::SafeMode(_) => true, @@ -1690,13 +1599,8 @@ mod runtime { pub type Inflation = pallet_inflation; #[runtime::pallet_index(36)] pub type Assets = pallet_assets; - #[runtime::pallet_index(37)] - pub type PriceAggregator = pallet_price_aggregator; - #[runtime::pallet_index(38)] - pub type Oracle = orml_oracle; - #[runtime::pallet_index(39)] - pub type OracleMembership = pallet_membership; - + // skip 37 - price_aggregator previously + // skip 38/39 - oracle and oracle_membership previously #[runtime::pallet_index(40)] pub type Authorship = pallet_authorship; #[runtime::pallet_index(41)] @@ -1809,13 +1713,24 @@ pub type Executive = frame_executive::Executive< Migrations, >; +parameter_types! { + pub const PriceAggregatorPalletStr: &'static str = "PriceAggregator"; + pub const OraclePalletStr: &'static str = "Oracle"; + pub const OracleMembershipPalletStr: &'static str = "OracleMembership"; +} + /// All migrations that will run on the next runtime upgrade. /// /// __NOTE:__ THE ORDER IS IMPORTANT. pub type Migrations = (Unreleased, Permanent); /// Unreleased migrations. Add new ones here: -pub type Unreleased = (); +pub type Unreleased = ( + pallet_dapp_staking::migration::versioned_migrations::V11ToV12, + frame_support::migrations::RemovePallet, + frame_support::migrations::RemovePallet, + frame_support::migrations::RemovePallet, +); /// Migrations/checks that do not need to be versioned and can run on every upgrade. pub type Permanent = (pallet_xcm::migration::MigrateToLatestXcmVersion,); @@ -1908,9 +1823,7 @@ mod benches { [pallet_unified_accounts, UnifiedAccounts] [xcm_benchmarks_generic, XcmGeneric] [xcm_benchmarks_fungible, XcmFungible] - [pallet_price_aggregator, PriceAggregator] [pallet_collective_proxy, CollectiveProxy] - [orml_oracle, Oracle] [pallet_tx_pause, TxPause] [pallet_safe_mode, SafeMode] ); diff --git a/runtime/shibuya/src/weights/mod.rs b/runtime/shibuya/src/weights/mod.rs index 6597d637e..9cae6ce46 100644 --- a/runtime/shibuya/src/weights/mod.rs +++ b/runtime/shibuya/src/weights/mod.rs @@ -20,7 +20,6 @@ mod block_weights; mod extrinsic_weights; pub mod frame_system_extensions; -pub mod orml_oracle; pub mod pallet_assets; pub mod pallet_balances; pub mod pallet_dapp_staking; diff --git a/runtime/shibuya/src/weights/orml_oracle.rs b/runtime/shibuya/src/weights/orml_oracle.rs deleted file mode 100644 index c8104cf5f..000000000 --- a/runtime/shibuya/src/weights/orml_oracle.rs +++ /dev/null @@ -1,91 +0,0 @@ - -// This file is part of Astar. - -// Copyright (C) Stake Technologies Pte.Ltd. -// SPDX-License-Identifier: GPL-3.0-or-later - -// Astar is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. - -// Astar is distributed in the hope that it will be useful, -// 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. - -// You should have received a copy of the GNU General Public License -// along with Astar. If not, see . - -//! Autogenerated weights for `orml_oracle` -//! -//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 32.0.0 -//! DATE: 2025-12-19, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` -//! WORST CASE MAP SIZE: `1000000` -//! HOSTNAME: `gh-runner-01-ovh`, CPU: `Intel(R) Xeon(R) E-2236 CPU @ 3.40GHz` -//! WASM-EXECUTION: `Compiled`, CHAIN: `None`, DB CACHE: 1024 - -// Executed Command: -// frame-omni-bencher -// v1 -// benchmark -// pallet -// --runtime=./target/release/wbuild/shibuya-runtime/shibuya_runtime.compact.compressed.wasm -// --steps=50 -// --repeat=20 -// --pallet=orml_oracle -// --extrinsic=* -// --wasm-execution=compiled -// --heap-pages=4096 -// --output=./benchmark-results/shibuya/runtime/oracle_weights.rs -// --template=./scripts/templates/runtime-weight-template.hbs - -#![cfg_attr(rustfmt, rustfmt_skip)] -#![allow(unused_parens)] -#![allow(unused_imports)] -#![allow(missing_docs)] -#![allow(dead_code)] - -use frame_support::{traits::Get, weights::Weight}; -use core::marker::PhantomData; - -/// Weight functions for `orml_oracle`. -pub struct SubstrateWeight(PhantomData); -impl orml_oracle::WeightInfo for SubstrateWeight { - /// Storage: `OracleMembership::Members` (r:1 w:0) - /// Proof: `OracleMembership::Members` (`max_values`: Some(1), `max_size`: Some(513), added: 1008, mode: `MaxEncodedLen`) - /// Storage: `Oracle::HasDispatched` (r:1 w:1) - /// Proof: `Oracle::HasDispatched` (`max_values`: Some(1), `max_size`: Some(257), added: 752, mode: `MaxEncodedLen`) - /// Storage: `Timestamp::Now` (r:1 w:0) - /// Proof: `Timestamp::Now` (`max_values`: Some(1), `max_size`: Some(8), added: 503, mode: `MaxEncodedLen`) - /// Storage: `Oracle::RawValues` (r:3 w:1) - /// Proof: `Oracle::RawValues` (`max_values`: None, `max_size`: Some(73), added: 2548, mode: `MaxEncodedLen`) - /// Storage: `Oracle::Values` (r:1 w:0) - /// Proof: `Oracle::Values` (`max_values`: None, `max_size`: Some(33), added: 2508, mode: `MaxEncodedLen`) - /// The range of component `x` is `[0, 2]`. - fn feed_values(x: u32, ) -> Weight { - // Proof Size summary in bytes: - // Measured: `346` - // Estimated: `8634` - // Minimum execution time: 17_396_000 picoseconds. - Weight::from_parts(18_293_172, 0) - .saturating_add(Weight::from_parts(0, 8634)) - // Standard Error: 64_988 - .saturating_add(Weight::from_parts(16_404_825, 0).saturating_mul(x.into())) - .saturating_add(T::DbWeight::get().reads(3)) - .saturating_add(T::DbWeight::get().reads((4_u64).saturating_mul(x.into()))) - .saturating_add(T::DbWeight::get().writes(1)) - .saturating_add(T::DbWeight::get().writes((1_u64).saturating_mul(x.into()))) - } - /// Storage: `Oracle::HasDispatched` (r:0 w:1) - /// Proof: `Oracle::HasDispatched` (`max_values`: Some(1), `max_size`: Some(257), added: 752, mode: `MaxEncodedLen`) - fn on_finalize() -> Weight { - // Proof Size summary in bytes: - // Measured: `0` - // Estimated: `0` - // Minimum execution time: 2_388_000 picoseconds. - Weight::from_parts(2_475_000, 0) - .saturating_add(Weight::from_parts(0, 0)) - .saturating_add(T::DbWeight::get().writes(1)) - } -} diff --git a/runtime/shiden/Cargo.toml b/runtime/shiden/Cargo.toml index 91e5f7105..8970ab0b9 100644 --- a/runtime/shiden/Cargo.toml +++ b/runtime/shiden/Cargo.toml @@ -101,7 +101,6 @@ xcm-executor = { workspace = true } xcm-runtime-apis = { workspace = true } # orml dependencies -orml-oracle = { workspace = true } orml-xcm-support = { workspace = true } orml-xtokens = { workspace = true } @@ -125,7 +124,6 @@ pallet-evm-precompile-sr25519 = { workspace = true } pallet-evm-precompile-substrate-ecdsa = { workspace = true } pallet-evm-precompile-xcm = { workspace = true } pallet-inflation = { workspace = true } -pallet-price-aggregator = { workspace = true } pallet-xc-asset-config = { workspace = true } pallet-xcm = { workspace = true } @@ -206,14 +204,12 @@ std = [ "pallet-proxy/std", "pallet-timestamp/std", "pallet-vesting/std", - "orml-oracle/std", "sp-offchain/std", "sp-session/std", "pallet-sudo/std", "pallet-transaction-payment/std", "pallet-transaction-payment-rpc-runtime-api/std", "pallet-xcm/std", - "pallet-price-aggregator/std", "parachain-info/std", "polkadot-parachain/std", "polkadot-primitives/std", @@ -274,7 +270,6 @@ runtime-benchmarks = [ "astar-primitives/runtime-benchmarks", "pallet-assets/runtime-benchmarks", "pallet-dynamic-evm-base-fee/runtime-benchmarks", - "pallet-price-aggregator/runtime-benchmarks", "cumulus-primitives-utility/runtime-benchmarks", "cumulus-pallet-parachain-system/runtime-benchmarks", "cumulus-pallet-xcmp-queue/runtime-benchmarks", @@ -301,7 +296,6 @@ runtime-benchmarks = [ "cumulus-primitives-core/runtime-benchmarks", "pallet-message-queue/runtime-benchmarks", "parachains-common/runtime-benchmarks", - "orml-oracle/runtime-benchmarks", "xcm/runtime-benchmarks", ] try-runtime = [ @@ -314,8 +308,6 @@ try-runtime = [ "frame-system/try-runtime", "pallet-aura/try-runtime", "pallet-balances/try-runtime", - "orml-oracle/try-runtime", - "pallet-price-aggregator/try-runtime", "pallet-membership/try-runtime", "pallet-dapp-staking/try-runtime", "pallet-inflation/try-runtime", diff --git a/runtime/shiden/src/genesis_config.rs b/runtime/shiden/src/genesis_config.rs index b8f911f90..cdef2b7d7 100644 --- a/runtime/shiden/src/genesis_config.rs +++ b/runtime/shiden/src/genesis_config.rs @@ -18,7 +18,7 @@ use crate::*; use astar_primitives::{ - dapp_staking::FIXED_TIER_SLOTS_ARGS, evm::EVM_REVERT_CODE, genesis::GenesisAccount, + evm::EVM_REVERT_CODE, genesis::GenesisAccount, parachain::SHIDEN_ID, }; @@ -148,23 +148,12 @@ pub fn default_config(para_id: u32) -> serde_json::Value { }, ], slots_per_tier, - slot_number_args: FIXED_TIER_SLOTS_ARGS, safeguard: Some(false), tier_rank_multipliers, ..Default::default() }, inflation: Default::default(), - oracle_membership: OracleMembershipConfig { - members: vec![alice.account_id(), bob.account_id()] - .try_into() - .expect("Assumption is that at least two members will be allowed."), - ..Default::default() - }, - price_aggregator: PriceAggregatorConfig { - circular_buffer: vec![CurrencyAmount::from_rational(5, 10)] - .try_into() - .expect("Must work since buffer should have at least a single value."), - }, + }; serde_json::to_value(&config).expect("Could not build genesis config.") diff --git a/runtime/shiden/src/lib.rs b/runtime/shiden/src/lib.rs index 59d0d3ad3..171424e98 100644 --- a/runtime/shiden/src/lib.rs +++ b/runtime/shiden/src/lib.rs @@ -88,8 +88,7 @@ use astar_primitives::{ PeriodNumber, RankedTier, SmartContract, FIXED_NUMBER_OF_TIER_SLOTS, }, evm::{EVMFungibleAdapterWrapper, EvmRevertCodeHandler}, - governance::OracleMembershipInst, - oracle::{CurrencyAmount, CurrencyId, DummyCombineData, Price}, + xcm::AssetLocationIdConverter, Address, AssetId, BlockNumber, Hash, Header, Nonce, UnfreezeChainOnFailedMigration, }; @@ -446,7 +445,6 @@ impl pallet_dapp_staking::Config for Runtime { type EraRewardSpanLength = ConstU32<16>; type RewardRetentionInPeriods = ConstU32<3>; type MaxNumberOfContracts = ConstU32<{ FIXED_NUMBER_OF_TIER_SLOTS as u32 }>; - type MaxNumberOfContractsLegacy = ConstU32<500>; type MaxUnlockingChunks = ConstU32<8>; type MinimumLockedAmount = MinimumStakingAmount; type UnlockingPeriod = ConstU32<4>; @@ -1113,94 +1111,6 @@ impl pallet_proxy::Config for Runtime { type AnnouncementDepositFactor = AnnouncementDepositFactor; } -parameter_types! { - pub const NativeCurrencyId: CurrencyId = CurrencyId::SDN; - // Aggregate values for one day. - pub const AggregationDuration: BlockNumber = DAYS; -} - -impl pallet_price_aggregator::Config for Runtime { - type MaxValuesPerBlock = ConstU32<8>; - type ProcessBlockValues = pallet_price_aggregator::MedianBlockValue; - type NativeCurrencyId = NativeCurrencyId; - // 7 days - type CircularBufferLength = ConstU32<7>; - type AggregationDuration = AggregationDuration; - type WeightInfo = pallet_price_aggregator::weights::SubstrateWeight; -} - -#[cfg(feature = "runtime-benchmarks")] -pub struct OracleBenchmarkHelper; -#[cfg(feature = "runtime-benchmarks")] -impl orml_oracle::BenchmarkHelper> for OracleBenchmarkHelper { - fn get_currency_id_value_pairs() -> sp_runtime::BoundedVec<(CurrencyId, Price), ConstU32<2>> { - sp_runtime::BoundedVec::try_from(vec![ - (CurrencyId::ASTR, Price::from_rational(15, 100)), - (CurrencyId::ASTR, Price::from_rational(15, 100)), - ]) - .expect("out of bounds") - } -} - -parameter_types! { - // Cannot specify `Root` so need to do it like this, unfortunately. - pub RootOperatorAccountId: AccountId = AccountId::from([0xffu8; 32]); -} - -impl orml_oracle::Config for Runtime { - type OnNewData = PriceAggregator; - type CombineData = DummyCombineData; - type Time = Timestamp; - type OracleKey = CurrencyId; - type OracleValue = Price; - type RootOperatorAccountId = RootOperatorAccountId; - #[cfg(feature = "runtime-benchmarks")] - type Members = OracleMembershipWrapper; - #[cfg(not(feature = "runtime-benchmarks"))] - type Members = OracleMembership; - type MaxHasDispatchedSize = ConstU32<8>; - type WeightInfo = weights::orml_oracle::SubstrateWeight; - #[cfg(feature = "runtime-benchmarks")] - type MaxFeedValues = ConstU32<2>; - #[cfg(not(feature = "runtime-benchmarks"))] - type MaxFeedValues = ConstU32<1>; - #[cfg(feature = "runtime-benchmarks")] - type BenchmarkHelper = OracleBenchmarkHelper; -} - -impl pallet_membership::Config for Runtime { - type RuntimeEvent = RuntimeEvent; - type AddOrigin = EnsureRoot; - type RemoveOrigin = EnsureRoot; - type SwapOrigin = EnsureRoot; - type ResetOrigin = EnsureRoot; - type PrimeOrigin = EnsureRoot; - - type MembershipInitialized = (); - type MembershipChanged = (); - type MaxMembers = ConstU32<16>; - type WeightInfo = pallet_membership::weights::SubstrateWeight; -} - -/// OracleMembership wrapper used by benchmarks -#[cfg(feature = "runtime-benchmarks")] -pub struct OracleMembershipWrapper; - -#[cfg(feature = "runtime-benchmarks")] -impl frame_support::traits::SortedMembers for OracleMembershipWrapper { - fn sorted_members() -> Vec { - OracleMembership::sorted_members() - } - - fn add(account: &AccountId) { - use alloc::borrow::ToOwned; - frame_support::assert_ok!(OracleMembership::add_member( - frame_system::RawOrigin::Root.into(), - account.to_owned().into() - )); - } -} - parameter_types! { pub MbmServiceWeight: Weight = Perbill::from_percent(50) * RuntimeBlockWeights::get().max_block; } @@ -1270,13 +1180,8 @@ mod runtime { pub type DappStaking = pallet_dapp_staking; #[runtime::pallet_index(36)] pub type Assets = pallet_assets; - #[runtime::pallet_index(37)] - pub type PriceAggregator = pallet_price_aggregator; - #[runtime::pallet_index(38)] - pub type Oracle = orml_oracle; - #[runtime::pallet_index(39)] - pub type OracleMembership = pallet_membership; - + // skip 37 - price_aggregator previously + // skip 38/39 - oracle and oracle_membership previously #[runtime::pallet_index(40)] pub type Authorship = pallet_authorship; #[runtime::pallet_index(41)] @@ -1356,13 +1261,24 @@ pub type Executive = frame_executive::Executive< Migrations, >; +parameter_types! { + pub const PriceAggregatorPalletStr: &'static str = "PriceAggregator"; + pub const OraclePalletStr: &'static str = "Oracle"; + pub const OracleMembershipPalletStr: &'static str = "OracleMembership"; +} + /// All migrations that will run on the next runtime upgrade. /// /// __NOTE:__ THE ORDER IS IMPORTANT. pub type Migrations = (Unreleased, Permanent); /// Unreleased migrations. Add new ones here: -pub type Unreleased = (); +pub type Unreleased = ( + pallet_dapp_staking::migration::versioned_migrations::V11ToV12, + frame_support::migrations::RemovePallet, + frame_support::migrations::RemovePallet, + frame_support::migrations::RemovePallet, +); /// Migrations/checks that do not need to be versioned and can run on every upgrade. pub type Permanent = (pallet_xcm::migration::MigrateToLatestXcmVersion,); @@ -1449,8 +1365,6 @@ mod benches { [pallet_dynamic_evm_base_fee, DynamicEvmBaseFee] [xcm_benchmarks_generic, XcmGeneric] [xcm_benchmarks_fungible, XcmFungible] - [pallet_price_aggregator, PriceAggregator] - [orml_oracle, Oracle] ); } diff --git a/runtime/shiden/src/weights/mod.rs b/runtime/shiden/src/weights/mod.rs index 8e3d70eec..16e360fa8 100644 --- a/runtime/shiden/src/weights/mod.rs +++ b/runtime/shiden/src/weights/mod.rs @@ -20,7 +20,6 @@ mod block_weights; mod extrinsic_weights; pub mod frame_system_extensions; -pub mod orml_oracle; pub mod pallet_assets; pub mod pallet_dapp_staking; pub mod pallet_inflation; diff --git a/runtime/shiden/src/weights/orml_oracle.rs b/runtime/shiden/src/weights/orml_oracle.rs deleted file mode 100644 index 2ee83fc65..000000000 --- a/runtime/shiden/src/weights/orml_oracle.rs +++ /dev/null @@ -1,91 +0,0 @@ - -// This file is part of Astar. - -// Copyright (C) Stake Technologies Pte.Ltd. -// SPDX-License-Identifier: GPL-3.0-or-later - -// Astar is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. - -// Astar is distributed in the hope that it will be useful, -// 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. - -// You should have received a copy of the GNU General Public License -// along with Astar. If not, see . - -//! Autogenerated weights for `orml_oracle` -//! -//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 32.0.0 -//! DATE: 2025-12-19, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` -//! WORST CASE MAP SIZE: `1000000` -//! HOSTNAME: `gh-runner-01-ovh`, CPU: `Intel(R) Xeon(R) E-2236 CPU @ 3.40GHz` -//! WASM-EXECUTION: `Compiled`, CHAIN: `None`, DB CACHE: 1024 - -// Executed Command: -// frame-omni-bencher -// v1 -// benchmark -// pallet -// --runtime=./target/release/wbuild/shiden-runtime/shiden_runtime.compact.compressed.wasm -// --steps=50 -// --repeat=20 -// --pallet=orml_oracle -// --extrinsic=* -// --wasm-execution=compiled -// --heap-pages=4096 -// --output=./benchmark-results/shiden/runtime/oracle_weights.rs -// --template=./scripts/templates/runtime-weight-template.hbs - -#![cfg_attr(rustfmt, rustfmt_skip)] -#![allow(unused_parens)] -#![allow(unused_imports)] -#![allow(missing_docs)] -#![allow(dead_code)] - -use frame_support::{traits::Get, weights::Weight}; -use core::marker::PhantomData; - -/// Weight functions for `orml_oracle`. -pub struct SubstrateWeight(PhantomData); -impl orml_oracle::WeightInfo for SubstrateWeight { - /// Storage: `OracleMembership::Members` (r:1 w:0) - /// Proof: `OracleMembership::Members` (`max_values`: Some(1), `max_size`: Some(513), added: 1008, mode: `MaxEncodedLen`) - /// Storage: `Oracle::HasDispatched` (r:1 w:1) - /// Proof: `Oracle::HasDispatched` (`max_values`: Some(1), `max_size`: Some(257), added: 752, mode: `MaxEncodedLen`) - /// Storage: `Timestamp::Now` (r:1 w:0) - /// Proof: `Timestamp::Now` (`max_values`: Some(1), `max_size`: Some(8), added: 503, mode: `MaxEncodedLen`) - /// Storage: `Oracle::RawValues` (r:3 w:1) - /// Proof: `Oracle::RawValues` (`max_values`: None, `max_size`: Some(73), added: 2548, mode: `MaxEncodedLen`) - /// Storage: `Oracle::Values` (r:1 w:0) - /// Proof: `Oracle::Values` (`max_values`: None, `max_size`: Some(33), added: 2508, mode: `MaxEncodedLen`) - /// The range of component `x` is `[0, 2]`. - fn feed_values(x: u32, ) -> Weight { - // Proof Size summary in bytes: - // Measured: `280` - // Estimated: `8634` - // Minimum execution time: 17_221_000 picoseconds. - Weight::from_parts(17_970_737, 0) - .saturating_add(Weight::from_parts(0, 8634)) - // Standard Error: 65_738 - .saturating_add(Weight::from_parts(15_092_004, 0).saturating_mul(x.into())) - .saturating_add(T::DbWeight::get().reads(3)) - .saturating_add(T::DbWeight::get().reads((4_u64).saturating_mul(x.into()))) - .saturating_add(T::DbWeight::get().writes(1)) - .saturating_add(T::DbWeight::get().writes((1_u64).saturating_mul(x.into()))) - } - /// Storage: `Oracle::HasDispatched` (r:0 w:1) - /// Proof: `Oracle::HasDispatched` (`max_values`: Some(1), `max_size`: Some(257), added: 752, mode: `MaxEncodedLen`) - fn on_finalize() -> Weight { - // Proof Size summary in bytes: - // Measured: `0` - // Estimated: `0` - // Minimum execution time: 2_272_000 picoseconds. - Weight::from_parts(2_369_000, 0) - .saturating_add(Weight::from_parts(0, 0)) - .saturating_add(T::DbWeight::get().writes(1)) - } -} diff --git a/tests/integration/Cargo.toml b/tests/integration/Cargo.toml index b6a293ef8..d1e1df5fa 100644 --- a/tests/integration/Cargo.toml +++ b/tests/integration/Cargo.toml @@ -29,7 +29,6 @@ cumulus-primitives-parachain-inherent = { workspace = true } cumulus-test-relay-sproof-builder = { workspace = true } frame-support = { workspace = true } frame-system = { workspace = true } -orml-oracle = { workspace = true } pallet-assets = { workspace = true } pallet-aura = { workspace = true } pallet-balances = { workspace = true } @@ -64,7 +63,6 @@ pallet-ethereum-checked = { workspace = true } pallet-evm-precompile-assets-erc20 = { workspace = true } pallet-evm-precompile-dispatch = { workspace = true } pallet-inflation = { workspace = true } -pallet-price-aggregator = { workspace = true } pallet-unified-accounts = { workspace = true } precompile-utils = { workspace = true } unified-accounts-chain-extension-types = { workspace = true } @@ -99,7 +97,6 @@ std = [ "hex/std", "libsecp256k1/std", "moonbeam-rpc-primitives-debug?/std", - "orml-oracle/std", "pallet-assets/std", "pallet-collective/std", "sp-trie/std", @@ -121,7 +118,6 @@ std = [ "pallet-safe-mode/std", "pallet-tx-pause/std", "pallet-membership/std", - "pallet-price-aggregator/std", "cumulus-test-relay-sproof-builder/std", "pallet-proxy/std", "pallet-unified-accounts/std", diff --git a/tests/integration/src/lib.rs b/tests/integration/src/lib.rs index fca7980b5..2aac72903 100644 --- a/tests/integration/src/lib.rs +++ b/tests/integration/src/lib.rs @@ -41,8 +41,6 @@ mod dapp_staking; #[cfg(any(feature = "shibuya", feature = "shiden", feature = "astar"))] mod assets_chain_extensions; -#[cfg(any(feature = "shibuya", feature = "shiden", feature = "astar"))] -mod oracle; #[cfg(any(feature = "shibuya", feature = "shiden", feature = "astar"))] mod evm_tracing; diff --git a/tests/integration/src/oracle.rs b/tests/integration/src/oracle.rs deleted file mode 100644 index 44b5249b0..000000000 --- a/tests/integration/src/oracle.rs +++ /dev/null @@ -1,90 +0,0 @@ -// This file is part of Astar. - -// Copyright (C) Stake Technologies Pte.Ltd. -// SPDX-License-Identifier: GPL-3.0-or-later - -// Astar is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. - -// Astar is distributed in the hope that it will be useful, -// 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. - -// You should have received a copy of the GNU General Public License -// along with Astar. If not, see . - -use crate::setup::*; - -use astar_primitives::oracle::{Price, PriceProvider}; -use pallet_price_aggregator::{IntermediateValueAggregator, ValueAggregator}; - -#[test] -fn price_submission_works() { - new_test_ext().execute_with(|| { - let native_currency_id = - ::NativeCurrencyId::get(); - assert_eq!(PriceAggregator::average_price(), INIT_PRICE, "Sanity check"); - - // 0. Need to set limit block to something sensible, otherwise we'll waste time on many redundant iterations - let limit_block = 10; - IntermediateValueAggregator::::put(ValueAggregator::new(limit_block)); - - // 1. Submit a price for a valid asset - the native currency - let price_1 = Price::from_rational(15, 100); - assert_ok!(Oracle::feed_values( - RuntimeOrigin::signed(ALICE.clone()), - vec![(native_currency_id, price_1)].try_into().unwrap() - )); - - let price_2 = Price::from_rational(17, 100); - assert_ok!(Oracle::feed_values( - RuntimeOrigin::signed(BOB.clone()), - vec![(native_currency_id, price_2)].try_into().unwrap() - )); - - // 2. Advance a block, and check price aggregator intermediate state is as expected - // (perhaps a bit detailed, but still good to check whether it's integrated) - run_for_blocks(1); - let expected_average = (price_1 + price_2) * Price::from_rational(1, 2); - assert_eq!( - IntermediateValueAggregator::::get().average(), - expected_average - ); - - // 3. Keep advancing blocks, adding new values only each other block, and verify the average is as expected at the end - for i in System::block_number() + 1..limit_block { - if i % 2 == 0 { - let step = Price::from_rational(i as u128 % 5, 100); - - assert_ok!(Oracle::feed_values( - RuntimeOrigin::signed(ALICE.clone()), - vec![(native_currency_id, price_1 + step)] - .try_into() - .unwrap() - )); - assert_ok!(Oracle::feed_values( - RuntimeOrigin::signed(BOB.clone()), - vec![(native_currency_id, price_2 - step)] - .try_into() - .unwrap() - )); - } - run_for_blocks(1); - } - - // 4. Execute limit block and verify state is updated as expected - run_for_blocks(2); // Need to run on_finalize of the limit block - let expected_moving_average = (expected_average + INIT_PRICE) * Price::from_rational(1, 2); - assert_eq!(PriceAggregator::average_price(), expected_moving_average); - - // 5. Run until next limit block without any transactions, don't expect any changes - let limit_block = limit_block * 2; - IntermediateValueAggregator::::put(ValueAggregator::new(limit_block)); - - run_to_block(limit_block + 1); - assert_eq!(PriceAggregator::average_price(), expected_moving_average); - }) -} diff --git a/tests/integration/src/setup.rs b/tests/integration/src/setup.rs index b213172ec..78db259a6 100644 --- a/tests/integration/src/setup.rs +++ b/tests/integration/src/setup.rs @@ -38,7 +38,7 @@ pub use astar_primitives::governance::{ TechnicalCommitteeCollectiveInst, TechnicalCommitteeMembershipInst, }; pub use astar_primitives::{ - genesis::GenesisAccount, governance::OracleMembershipInst, oracle::Price, BlockNumber, + genesis::GenesisAccount, BlockNumber, }; #[cfg(feature = "shibuya")] @@ -102,7 +102,6 @@ pub const CAT: AccountId32 = AccountId32::new([3_u8; 32]); pub const INITIAL_AMOUNT: u128 = 100_000 * UNIT; -pub const INIT_PRICE: Price = Price::from_rational(1, 10); pub type SystemError = frame_system::Error; use cumulus_pallet_parachain_system::RelaychainDataProvider; @@ -184,24 +183,6 @@ impl ExtBuilder { ) .unwrap(); - // Setup initial oracle members - as BuildStorage>::assimilate_storage( - &pallet_membership::GenesisConfig:: { - members: vec![ALICE, BOB].try_into().expect("Safe to assume at least 2 members are supported."), - ..Default::default() - }, - &mut t) - .unwrap(); - - // Setup initial native currency price - as BuildStorage>::assimilate_storage( - &pallet_price_aggregator::GenesisConfig:: { - circular_buffer: vec![INIT_PRICE].try_into().unwrap(), - }, - &mut t, - ) - .unwrap(); - // Needed to trigger initial inflation config setting. as BuildStorage>::assimilate_storage( &pallet_inflation::GenesisConfig::default(), diff --git a/tests/xcm-simulator/src/mocks/parachain.rs b/tests/xcm-simulator/src/mocks/parachain.rs index f1254ba93..b0362ddde 100644 --- a/tests/xcm-simulator/src/mocks/parachain.rs +++ b/tests/xcm-simulator/src/mocks/parachain.rs @@ -646,7 +646,6 @@ impl pallet_dapp_staking::Config for Runtime { type EraRewardSpanLength = ConstU32<1>; type RewardRetentionInPeriods = ConstU32<2>; type MaxNumberOfContracts = ConstU32<10>; - type MaxNumberOfContractsLegacy = ConstU32<10>; type MaxUnlockingChunks = ConstU32<5>; type MinimumLockedAmount = ConstU128<3>; type UnlockingPeriod = ConstU32<2>;